diff --git a/CHANGELOG.md b/CHANGELOG.md
index 38164b1..07b53c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,24 @@
+## Turtle 0.1.4
+
+* `Turtle` Upgrades
+ * `turtle` will return an empty turtle (#112)
+ * `turtle` now splats to script methods, enabling more complex input binding (#121)
+ * `LSystem` is faster and more flexible (#116)
+* New Properties:
+ * `get/set_Opacity` (#115)
+ * `get/set_PathAnimation` (#117)
+ * `get/set_Width/Height` (#125)
+* New Methods:
+ * `HorizontalLine/VerticalLine` (#126)
+ * `Petal` (#119)
+ * `FlowerPetal` (#124)
+ * `Spirolateral` (#120)
+ * `StepSpiral` (#122)
+* Fixes:
+ * `Turtle.Towards()` returns a relative angle (#123)
+
+---
+
## Turtle 0.1.3
* Fixing `Get-Turtle` inline sets (#108, #107)
diff --git a/Commands/Get-Turtle.ps1 b/Commands/Get-Turtle.ps1
index 7fc7f74..e9fd1dd 100644
--- a/Commands/Get-Turtle.ps1
+++ b/Commands/Get-Turtle.ps1
@@ -88,7 +88,8 @@ function Get-Turtle {
# We want to keep track of the current member,
# and continue to the next word until we find a member name.
$currentMember = $null
- $outputTurtle = $false
+ # We want to output the turtle by default, in case we were called with no parameters.
+ $outputTurtle = $true
# To do this in one pass, we will iterate through the words and arguments.
# We use an indexed loop so we can skip past claimed arguments.
@@ -116,15 +117,13 @@ function Get-Turtle {
}
# Now we know how long it took to get to the next member name.
- # And we can determine if we have any parameters
+ # And we can determine if we have any parameters.
+ # (it is important that we always force any parameters into an array)
$argList =
- if ($methodArgIndex -eq ($argIndex + 1)) {
- @()
- }
- else {
+ @(if ($methodArgIndex -ne ($argIndex + 1)) {
$wordsAndArguments[($argIndex + 1)..($methodArgIndex - 1)]
$argIndex = $methodArgIndex - 1
- }
+ })
# Look up the member information for the current member.
$memberInfo = $turtleType.Members[$currentMember]
@@ -145,8 +144,18 @@ function Get-Turtle {
) {
# If we have arguments,
if ($argList) {
- # pass them to the method.
- $currentTurtle.$currentMember.Invoke($argList)
+ # and we have a script method
+ if ($memberInfo -is [Management.Automation.Runspaces.ScriptMethodData]) {
+ # set this to the current turtle
+ $this = $currentTurtle
+ # and call the script, splatting positional parameters
+ # (this allows more complex binding, like ValueFromRemainingArguments)
+ . $currentTurtle.$currentMember.Script @argList
+ } else {
+ # Otherwise, we pass the parameters directly to the method
+ $currentTurtle.$currentMember.Invoke($argList)
+ }
+
} else {
# otherwise, just invoke the method with no arguments.
$currentTurtle.$currentMember.Invoke()
diff --git a/Examples/BoxFractal.svg b/Examples/BoxFractal.svg
index 0c6a946..e745d7c 100644
--- a/Examples/BoxFractal.svg
+++ b/Examples/BoxFractal.svg
@@ -1,6 +1,7 @@
\ No newline at end of file
diff --git a/Examples/EndlessBoxFractal.svg b/Examples/EndlessBoxFractal.svg
index a0f3f41..b31525d 100644
--- a/Examples/EndlessBoxFractal.svg
+++ b/Examples/EndlessBoxFractal.svg
@@ -6,7 +6,8 @@
-
+
+
diff --git a/Examples/EndlessHilbert.svg b/Examples/EndlessHilbert.svg
index c130204..996cd0e 100644
--- a/Examples/EndlessHilbert.svg
+++ b/Examples/EndlessHilbert.svg
@@ -6,7 +6,8 @@
-
+
+
diff --git a/Examples/EndlessSierpinskiTrianglePattern.svg b/Examples/EndlessSierpinskiTrianglePattern.svg
index 0f93759..01fdacc 100644
--- a/Examples/EndlessSierpinskiTrianglePattern.svg
+++ b/Examples/EndlessSierpinskiTrianglePattern.svg
@@ -6,7 +6,8 @@
-
+
+
diff --git a/Examples/EndlessSnowflake.svg b/Examples/EndlessSnowflake.svg
index 17575f2..5e944d6 100644
--- a/Examples/EndlessSnowflake.svg
+++ b/Examples/EndlessSnowflake.svg
@@ -6,7 +6,8 @@
-
+
+
diff --git a/Examples/EndlessSpirolateral.svg b/Examples/EndlessSpirolateral.svg
new file mode 100644
index 0000000..2552f07
--- /dev/null
+++ b/Examples/EndlessSpirolateral.svg
@@ -0,0 +1,14 @@
+
\ No newline at end of file
diff --git a/Examples/EndlessSpirolateral.turtle.ps1 b/Examples/EndlessSpirolateral.turtle.ps1
new file mode 100644
index 0000000..7c9e0f1
--- /dev/null
+++ b/Examples/EndlessSpirolateral.turtle.ps1
@@ -0,0 +1,20 @@
+Push-Location $PSScriptRoot
+$myName = $MyInvocation.MyCommand.Name -replace '\.turtle\.ps1$'
+$turtle = turtle rotate -30 @('spirolateral',42,60,6,@(1,3),'rotate', 60 * 6 )|
+ Set-Turtle -Property PatternTransform -Value @{scale=0.33} |
+ set-turtle -property Fill -value '#4488ff' |
+ set-turtle -property FillRule -value 'evenodd' |
+ Set-Turtle -Property PatternAnimation -Value ([Ordered]@{
+ type = 'scale' ; values = 0.66,0.33, 0.66 ; repeatCount = 'indefinite' ;dur = "23s"; additive = 'sum'
+ }, [Ordered]@{
+ type = 'rotate' ; values = 0, 360 ;repeatCount = 'indefinite'; dur = "41s"; additive = 'sum'
+ }, [Ordered]@{
+ type = 'skewX' ; values = -30,30,-30;repeatCount = 'indefinite';dur = "83s";additive = 'sum'
+ }, [Ordered]@{
+ type = 'skewY' ; values = 30,-30, 30;repeatCount = 'indefinite';additive = 'sum';dur = "103s"
+ }, [Ordered]@{
+ type = 'translate';values = "0 0","42 42", "0 0";repeatCount = 'indefinite';additive = 'sum';dur = "117s"
+ })
+
+$turtle | save-turtle -Path "./$myName.svg" -Property Pattern
+Pop-Location
\ No newline at end of file
diff --git a/Examples/EndlessStepSpiral.svg b/Examples/EndlessStepSpiral.svg
new file mode 100644
index 0000000..4b6330d
--- /dev/null
+++ b/Examples/EndlessStepSpiral.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/Examples/EndlessStepSpiral.turtle.ps1 b/Examples/EndlessStepSpiral.turtle.ps1
new file mode 100644
index 0000000..e0550c3
--- /dev/null
+++ b/Examples/EndlessStepSpiral.turtle.ps1
@@ -0,0 +1,16 @@
+Push-Location $PSScriptRoot
+$myName = $MyInvocation.MyCommand.Name -replace '\.turtle\.ps1$'
+$turtle = turtle @('StepSpiral',16, 90, 16, 20, 'rotate',90 * 4) |
+ Set-Turtle -Property PatternTransform -Value @{scale=1} |
+ # set-turtle -property Fill -value 'currentColor' |
+ # set-turtle -property FillRule -value 'evenodd' |
+ Set-Turtle -Property PatternAnimation -Value ([Ordered]@{
+ type = 'scale' ; values = 0.66,0.33, 0.66 ; repeatCount = 'indefinite' ;dur = "23s"; additive = 'sum'
+ }, [Ordered]@{
+ type = 'rotate' ; values = 0, 360 ;repeatCount = 'indefinite'; dur = "41s"; additive = 'sum'
+ }, [Ordered]@{
+ type = 'translate';values = "0 0","42 42", "0 0";repeatCount = 'indefinite';additive = 'sum';dur = "117s"
+ })
+
+$turtle | save-turtle -Path "./$myName.svg" -Property Pattern
+Pop-Location
\ No newline at end of file
diff --git a/Examples/SierpinskiTriangle.svg b/Examples/SierpinskiTriangle.svg
index 30b944f..8d733a4 100644
--- a/Examples/SierpinskiTriangle.svg
+++ b/Examples/SierpinskiTriangle.svg
@@ -1,6 +1,7 @@
\ No newline at end of file
diff --git a/Turtle.psd1 b/Turtle.psd1
index 1d9bd46..68c522e 100644
--- a/Turtle.psd1
+++ b/Turtle.psd1
@@ -1,6 +1,6 @@
@{
# Version number of this module.
- ModuleVersion = '0.1.3'
+ ModuleVersion = '0.1.4'
# Description of the module
Description = "Turtles in a PowerShell"
# Script module or binary module file associated with this manifest.
@@ -37,95 +37,28 @@
# A URL to the license for this module.
LicenseURI = 'https://github.com/PowerShellWeb/Turtle/blob/main/LICENSE'
ReleaseNotes = @'
-## Turtle 0.1.3
-
-* Fixing `Get-Turtle` inline sets (#108, #107)
-* Fixing `.PNG/JPEG/WEBP` to no longer try to use msedge (#110)
-* Adding `Turtle.get/set_FillRule` to get or set the fill rule for the turtle. (#109)
-
----
-
-## Turtle 0.1.2
-
-* `Get-Turtle/Turtle` can now get or set properties or methods
+## Turtle 0.1.4
+
+* `Turtle` Upgrades
+ * `turtle` will return an empty turtle (#112)
+ * `turtle` now splats to script methods, enabling more complex input binding (#121)
+ * `LSystem` is faster and more flexible (#116)
+* New Properties:
+ * `get/set_Opacity` (#115)
+ * `get/set_PathAnimation` (#117)
+ * `get/set_Width/Height` (#125)
* New Methods:
- * `Turtle.Distance()` determines the distance to a point
- * `Turtle.Towards()` determines the angle to a point
- * `Turtle.Home()` sends the turtle to 0,0
- * `Turtle.lt/rt` aliases help original Logo compatibility
- * `Turtle.Save()` calls Save-Turtle
-* Explicitly exporting commands from module
-
----
-
-## Turtle 0.1.1
-
-* Updates:
- * `Turtle.get/set_ID` allows for turtle identifiers
- * `Turtle.ToString()` stringifies the SVG
+ * `HorizontalLine/VerticalLine` (#126)
+ * `Petal` (#119)
+ * `FlowerPetal` (#124)
+ * `Spirolateral` (#120)
+ * `StepSpiral` (#122)
* Fixes:
- * Fixing GoTo/Teleport (#90)
- * Fixing Position default (#85) (thanks @ninmonkey !)
- * Fixing Turtle Action ID (#89)
-* New:
- * `Turtle.Push()` pushes position/heading to a stack (#91)
- * `Turtle.Pop()` pops position/heading from a stack (#92)
- * `Turtle.get_Stack` gets the position stack (#93)
-* New Fractals:
- * `BinaryTree()` (#94)
- * `FractalPlant()` (#95)
+ * `Turtle.Towards()` returns a relative angle (#123)
---
-## Turtle 0.1
-
-* Initial Release
-* Builds a Turtle Graphics engine in PowerShell
-* Core commands
- * `Get-Turtle` (alias `turtle`) runs multiple moves
- * `New-Turtle` create a turtle
- * `Move-Turtle` performas a single move
- * `Set-Turtle` changes a turtle
- * `Save-Turtle` saves a turtle
-
-~~~PowerShell
-turtle Forward 10 Rotate 120 Forward 10 Roate 120 Forward 10 Rotate 120 |
- Set-Turtle Stroke '#4488ff' |
- Save-Turtle ./Triangle.svg
-~~~
-
-* Core Object
- * `.Heading` controls the turtle heading
- * `.Steps` stores a list of moves as an SVG path
- * `.IsPenDown` controls the pen
- * `.Forward()` moves forward at heading
- * `.Rotate()` rotates the heading
- * `.Square()` draws a square
- * `.Polygon()` draws a polygon
- * `.Circle()` draws a circle (or partial circle)
-* LSystems
- * Turtle can draw a L system. Several are included:
- * `BoxFractal`
- * `GosperCurve`
- * `HilbertCurve`
- * `KochCurve`
- * `KochIsland`
- * `KochSnowflake`
- * `MooreCurve`
- * `PeanoCurve`
- * `SierpinskiTriangle`
- * `SierpinskiCurve`
- * `SierpinskiSquareCurve`
- * `SierpinskiArrowheadCurve`
- * `TerdragonCurve`
- * `TwinDragonCurve`
-
-~~~PowerShell
-turtle SierpinskiTriangle 10 4 |
- Set-Turtle Stroke '#4488ff' |
- Save-Turtle ./SierpinskiTriangle.svg
-~~~
-
+Additional details available in the [CHANGELOG](https://github.com/PowerShellWeb/Turtle/blob/main/CHANGELOG.md)
'@
}
}
diff --git a/Turtle.tests.ps1 b/Turtle.tests.ps1
index ec2d3d9..62306f8 100644
--- a/Turtle.tests.ps1
+++ b/Turtle.tests.ps1
@@ -18,4 +18,33 @@ describe Turtle {
$png = New-Turtle | Move-Turtle SierpinskiTriangle 15 5 | Select-Object -ExpandProperty PNG
$png[1..3] -as 'char[]' -as 'string[]' -join '' | Should -Be PNG
}
+
+
+ context 'Turtle Directions' {
+ it 'Can tell you the way towards a point' {
+ $turtle = turtle
+ $turtle.Towards(0,1) | should -be 90
+ $turtle.Towards(1,1) | Should -be 45
+ $turtle.Towards(1,0) | should -be 0
+ $turtle.Towards(-1,1) | Should -be 135
+ $turtle.Towards(-1,0) | Should -be 180
+ $turtle.Towards(0,-1) | Should -be -90
+ }
+
+ it 'Will return a relative heading' {
+ $turtle = turtle
+ $turtle = $turtle.Rotate($turtle.Towards(1,1))
+ $turtle = $turtle.Forward($turtle.Distance(1,1))
+ $turtle.Heading | Should -be 45
+ [Math]::Round($turtle.Position.X,10) | Should -be 1
+ [Math]::Round($turtle.Position.Y,10) | Should -be 1
+ $turtle = $turtle.Rotate($turtle.Towards(2,2))
+ $turtle = $turtle.Forward($turtle.Distance(2,2))
+ $turtle.Heading | Should -be 45
+ [Math]::Round($turtle.Position.Y,10) | Should -be 2
+ [Math]::Round($turtle.Position.Y,10) | Should -be 2
+ }
+ }
+
+
}
diff --git a/Turtle.types.ps1xml b/Turtle.types.ps1xml
index 90d669a..4a2a1bc 100644
--- a/Turtle.types.ps1xml
+++ b/Turtle.types.ps1xml
@@ -15,6 +15,14 @@
+
+ ArcL
+ ArcLeft
+
+
+ ArcR
+ ArcRight
+
Back
Backward
@@ -31,6 +39,10 @@
fd
Forward
+
+ HLineBy
+ HorizontalLine
+
l
Left
@@ -75,6 +87,10 @@
up
PenUp
+
+ VLineBy
+ VerticalLine
+
xPos
xcor
@@ -83,6 +99,74 @@
yPos
ycor
+
+ ArcLeft
+
+
+
+ ArcRight
+
+
Backward
@@ -315,6 +399,45 @@ $null = foreach ($n in 1..$StepCount) {
$this.Rotate($Rotation)
}
+return $this
+
+
+
+ FlowerPetal
+
@@ -457,6 +580,27 @@ return $this.Teleport(0,0)
+
+ HorizontalLine
+
+
Jump
@@ -873,6 +1049,40 @@ return $this
+
+ Petal
+
+
Polygon
+
+ Spirolateral
+
+
Square
+
+
+ StepSpiral
+
@@ -1266,7 +1606,7 @@ return "$($this.SVG.OuterXml)"
.SYNOPSIS
Determines the angle towards a point
.DESCRIPTION
- Determines the angle from the turtle's current position towards a point.
+ Determines the angle from the turtle's current heading towards a point.
#>
param(
# The X-coordinate
@@ -1276,12 +1616,12 @@ param(
)
# Determine the delta from the turtle's current position to the specified point
-$deltaX = $this.Position.X - $X
-$deltaY = $this.Position.Y - $Y
+$deltaX = $X - $this.Position.X
+$deltaY = $Y - $this.Position.Y
# Calculate the angle in radians and convert to degrees
$angle = [Math]::Atan2($deltaY, $deltaX) * 180 / [Math]::PI
-# Return the angle rotate by 90 to account for the turtle's coordinate system
-return $angle + 90
+# Return the angle minus the current heading (modulo 360)
+return $angle - ($this.Heading % 360)
@@ -1329,6 +1669,26 @@ return $this.LSystem('FX+FX+', [Ordered]@{
+
+ VerticalLine
+
+
xcor