Skip to content

Commit acffdad

Browse files
Merge pull request #133 from PowerShellWeb/turtles-with-scissors
Turtle 0.1.5
2 parents 48531cd + 3df938f commit acffdad

File tree

11 files changed

+343
-43
lines changed

11 files changed

+343
-43
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## Turtle 0.1.5:
2+
3+
* New Shapes:
4+
* Scissor draws a pair of lines at an angle (#128)
5+
* ScissorPoly draws a polygon out of scissors (#129)
6+
* Fixes:
7+
* OffsetPath is now quoted (#130)
8+
* ArcLeft/Right distance fix (#131)
9+
10+
---
11+
112
## Turtle 0.1.4
213

314
* `Turtle` Upgrades

Examples/EndlessScissorPoly.svg

Lines changed: 14 additions & 0 deletions
Loading
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Push-Location $PSScriptRoot
2+
$turtle = turtle ScissorPoly 230 64 64 |
3+
Set-Turtle -Property PatternTransform -Value @{scale=0.33} |
4+
set-turtle -property Stroke -value '#224488' |
5+
set-turtle -property Fill -value '#4488ff' |
6+
Set-Turtle -Property FillRule -Value 'evenodd' |
7+
Set-Turtle -Property PatternAnimation -Value ([Ordered]@{
8+
type = 'scale' ; values = 1.33,0.66, 1.33 ; repeatCount = 'indefinite' ;dur = "23s"; additive = 'sum'
9+
}, [Ordered]@{
10+
type = 'rotate' ; values = 0, 360 ;repeatCount = 'indefinite'; dur = "41s"; additive = 'sum'
11+
}, [Ordered]@{
12+
type = 'skewX' ; values = -30,30,-30;repeatCount = 'indefinite';dur = "83s";additive = 'sum'
13+
}, [Ordered]@{
14+
type = 'skewY' ; values = 30,-30, 30;repeatCount = 'indefinite';additive = 'sum';dur = "103s"
15+
}, [Ordered]@{
16+
type = 'translate';values = "0 0","42 42", "0 0";repeatCount = 'indefinite';additive = 'sum';dur = "117s"
17+
})
18+
19+
$turtle | save-turtle -Path ./EndlessScissorPoly.svg -Property Pattern
20+
Pop-Location

Turtle.psd1

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@{
22
# Version number of this module.
3-
ModuleVersion = '0.1.4'
3+
ModuleVersion = '0.1.5'
44
# Description of the module
55
Description = "Turtles in a PowerShell"
66
# Script module or binary module file associated with this manifest.
@@ -37,24 +37,14 @@
3737
# A URL to the license for this module.
3838
LicenseURI = 'https://github.com/PowerShellWeb/Turtle/blob/main/LICENSE'
3939
ReleaseNotes = @'
40-
## Turtle 0.1.4
40+
## Turtle 0.1.5:
4141
42-
* `Turtle` Upgrades
43-
* `turtle` will return an empty turtle (#112)
44-
* `turtle` now splats to script methods, enabling more complex input binding (#121)
45-
* `LSystem` is faster and more flexible (#116)
46-
* New Properties:
47-
* `get/set_Opacity` (#115)
48-
* `get/set_PathAnimation` (#117)
49-
* `get/set_Width/Height` (#125)
50-
* New Methods:
51-
* `HorizontalLine/VerticalLine` (#126)
52-
* `Petal` (#119)
53-
* `FlowerPetal` (#124)
54-
* `Spirolateral` (#120)
55-
* `StepSpiral` (#122)
42+
* New Shapes:
43+
* Scissor draws a pair of lines at an angle (#128)
44+
* ScissorPoly draws a polygon out of scissors (#129)
5645
* Fixes:
57-
* `Turtle.Towards()` returns a relative angle (#123)
46+
* OffsetPath is now quoted (#130)
47+
* ArcLeft/Right distance fix (#131)
5848
5949
---
6050

Turtle.tests.ps1

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,26 @@ describe Turtle {
1919
$png[1..3] -as 'char[]' -as 'string[]' -join '' | Should -Be PNG
2020
}
2121

22+
it 'Can draw an arc' {
23+
$Radius = 1
24+
$t = turtle ArcRight $Radius 360
25+
$Heading = 180.0
26+
[Math]::Round($t.Width,1) | Should -Be ($Radius * 2)
27+
[Math]::Round($t.Heading,1) | Should -Be 360.0
28+
29+
$Radius = 1
30+
$Heading = 180.0
31+
$t = turtle ArcRight $Radius 180
32+
[Math]::Round($t.Width,1) | Should -Be ($Radius * 2)
33+
[Math]::Round($t.Heading,1) | Should -Be $Heading
34+
35+
$Radius = 1
36+
$Heading = 90.0
37+
$t = turtle ArcRight $Radius $Heading
38+
[Math]::Round($t.Width,1) | Should -Be ($Radius * 4)
39+
[Math]::Round($t.Heading,1) | Should -Be $Heading
40+
}
41+
2242

2343
context 'Turtle Directions' {
2444
it 'Can tell you the way towards a point' {

Turtle.types.ps1xml

Lines changed: 137 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,19 +151,33 @@ $Radius = 10,
151151
$Angle = 60
152152
)
153153

154-
155-
# Determine the absolute angle, for this
154+
# Determine the absolute angle, for this operation
156155
$absAngle = [Math]::Abs($angle)
157-
$circumferenceStep = ([Math]::PI * 2 * $Radius) / $absAngle
158156

159-
$iteration = $angle / [Math]::Floor($absAngle)
160-
$angleDelta = 0
161-
$null = while ([Math]::Abs($angleDelta) -lt $absAngle) {
162-
$this.Forward($circumferenceStep)
163-
$this.Rotate($iteration)
157+
if ($absAngle -eq 0) { return $this }
158+
159+
# Determine the circumference of a circle of this radius
160+
$Circumference = ((2 * $Radius) * [Math]::PI)
161+
162+
# Clamp the angle, as arcs beyond 360 just continue to circle
163+
$ClampedAngle =
164+
if ($absAngle -gt 360) { 360 }
165+
elseif ($absAngle -lt -360) { -360}
166+
else { $absAngle }
167+
# The circumference step is the circumference divided by our clamped angle
168+
$CircumferenceStep = $Circumference / [Math]::Floor($ClampedAngle)
169+
# The iteration is as close to one or negative one as possible
170+
$iteration = $angle / [Math]::Floor($absAngle)
171+
# Start off at iteration 1
172+
$angleDelta = $iteration
173+
# while we have not reached the angle
174+
while ([Math]::Abs($angleDelta) -le $absAngle) {
175+
# Rotate and move forward
176+
$null = $this.Rotate($iteration).Forward($CircumferenceStep)
164177
$angleDelta+=$iteration
165178
}
166179

180+
# Return this so we can keep the chain.
167181
return $this
168182
</Script>
169183
</ScriptMethod>
@@ -1188,6 +1202,111 @@ return $this | Save-Turtle @saveSplat
11881202

11891203
</Script>
11901204
</ScriptMethod>
1205+
<ScriptMethod>
1206+
<Name>Scissor</Name>
1207+
<Script>
1208+
&lt;#
1209+
.SYNOPSIS
1210+
Draws a Scissor
1211+
.DESCRIPTION
1212+
Draws a Scissor in turtle.
1213+
1214+
A Scissor is a pair of intersecting lines, drawn at an angle.
1215+
.EXAMPLE
1216+
Turtle Scissor Save ./Scissor.svg
1217+
#&gt;
1218+
param(
1219+
# The distance to travel
1220+
[double]
1221+
$Distance = 10,
1222+
1223+
# The interior angle of the scissors
1224+
[double]
1225+
$Angle = 60
1226+
)
1227+
1228+
1229+
$this.
1230+
Rotate($angle). # Rotate
1231+
Forward($distance). # Move Forward
1232+
Rotate($angle * -2). # Rotate Back
1233+
Forward($Distance). # Move Forward
1234+
Rotate($Angle) # Rotate
1235+
1236+
</Script>
1237+
</ScriptMethod>
1238+
<ScriptMethod>
1239+
<Name>ScissorPoly</Name>
1240+
<Script>
1241+
&lt;#
1242+
.SYNOPSIS
1243+
Draws a polygon made of Scissors
1244+
.DESCRIPTION
1245+
Draws a polygon made up of a series of Scissor shapes, followed by a rotation.
1246+
1247+
This countiues until the total angle is approximately 360.
1248+
.EXAMPLE
1249+
# When the angles are even divisors of 360, we get stars
1250+
Turtle ScissorPoly 84 60 72 save ./ScissorPolyStar.svg
1251+
.EXAMPLE
1252+
Turtle ScissorPoly 23 60 72 save ./ScissorPolyStar2.svg
1253+
.EXAMPLE
1254+
Turtle ScissorPoly 23 60 40 save ./ScissorPolyStar3.svg
1255+
.EXAMPLE
1256+
# When both angles exceed 180, the star starts to overlap
1257+
Turtle ScissorPoly 23 90 120 save ./ScissorPoly.svg
1258+
.EXAMPLE
1259+
# When the angle is _not_ an even multiple of 360, there is much more overlap
1260+
Turtle ScissorPoly 16 42 42 save ./ScissorPoly.svg
1261+
.EXAMPLE
1262+
# This can get very chaotic, if it takes a while to reach a multiple of 360
1263+
# Build N scissor polygons
1264+
foreach ($n in 60..72) {
1265+
Turtle ScissorPoly 16 $n $n save ./ScissorPoly-$n.svg
1266+
}
1267+
.EXAMPLE
1268+
Turtle ScissorPoly 16 69 69 save ./ScissorPoly-69.svg
1269+
.EXAMPLE
1270+
Turtle ScissorPoly 15 72 90 save ./ScissorPoly.svg
1271+
.EXAMPLE
1272+
# And angle of exactly 90 will produce a series of spokes
1273+
Turtle ScissorPoly 23 45 90 save ./Compass.svg
1274+
.EXAMPLE
1275+
# These spokes become pointy stars as we iterate past 90
1276+
foreach ($n in 91..99) {
1277+
Turtle ScissorPoly 23 45 $n save "./Scissor-45-$n.svg"
1278+
}
1279+
.EXAMPLE
1280+
Turtle ScissorPoly 23 45 98 save ./ScissorPoly-45-98.svg
1281+
.EXAMPLE
1282+
Turtle ScissorPoly 23 45 99 save ./ScissorPoly-45-99.svg
1283+
#&gt;
1284+
param(
1285+
# The distance of each side of the scissor
1286+
[double]
1287+
$Distance,
1288+
1289+
# The angle between each scissor
1290+
[double]
1291+
$Angle,
1292+
1293+
# The angle of each scissor, or the degree out of phase a regular N-gon would be.
1294+
[double]
1295+
$Phase
1296+
)
1297+
1298+
$totalTurn = 0
1299+
1300+
do {
1301+
$this = $this.Scissor($Distance, $Phase).Left($angle)
1302+
$totalTurn -= $angle
1303+
}
1304+
until (
1305+
(-not ([Math]::Round($totalTurn, 5) % 360 ))
1306+
)
1307+
1308+
</Script>
1309+
</ScriptMethod>
11911310
<ScriptMethod>
11921311
<Name>SierpinskiArrowheadCurve</Name>
11931312
<Script>
@@ -2088,7 +2207,16 @@ return ([pscustomobject]@{ X = 0; Y = 0 })
20882207
<ScriptProperty>
20892208
<Name>OffsetPath</Name>
20902209
<GetScriptBlock>
2091-
"offset-path: $($this.PathData);"
2210+
&lt;#
2211+
.SYNOPSIS
2212+
Gets the Turtle as an OffsetPath
2213+
.DESCRIPTION
2214+
Gets the Turtle as an offset path.
2215+
.LINK
2216+
https://developer.mozilla.org/en-US/docs/Web/CSS/offset-path
2217+
#&gt;
2218+
param()
2219+
"offset-path: path('$($this.PathData)');"
20922220
</GetScriptBlock>
20932221
</ScriptProperty>
20942222
<ScriptProperty>

Types/Turtle/ArcRight.ps1

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,31 @@ $Radius = 10,
1818
$Angle = 60
1919
)
2020

21-
22-
# Determine the absolute angle, for this
21+
# Determine the absolute angle, for this operation
2322
$absAngle = [Math]::Abs($angle)
24-
$circumferenceStep = ([Math]::PI * 2 * $Radius) / $absAngle
2523

26-
$iteration = $angle / [Math]::Floor($absAngle)
27-
$angleDelta = 0
28-
$null = while ([Math]::Abs($angleDelta) -lt $absAngle) {
29-
$this.Forward($circumferenceStep)
30-
$this.Rotate($iteration)
24+
if ($absAngle -eq 0) { return $this }
25+
26+
# Determine the circumference of a circle of this radius
27+
$Circumference = ((2 * $Radius) * [Math]::PI)
28+
29+
# Clamp the angle, as arcs beyond 360 just continue to circle
30+
$ClampedAngle =
31+
if ($absAngle -gt 360) { 360 }
32+
elseif ($absAngle -lt -360) { -360}
33+
else { $absAngle }
34+
# The circumference step is the circumference divided by our clamped angle
35+
$CircumferenceStep = $Circumference / [Math]::Floor($ClampedAngle)
36+
# The iteration is as close to one or negative one as possible
37+
$iteration = $angle / [Math]::Floor($absAngle)
38+
# Start off at iteration 1
39+
$angleDelta = $iteration
40+
# while we have not reached the angle
41+
while ([Math]::Abs($angleDelta) -le $absAngle) {
42+
# Rotate and move forward
43+
$null = $this.Rotate($iteration).Forward($CircumferenceStep)
3144
$angleDelta+=$iteration
3245
}
3346

47+
# Return this so we can keep the chain.
3448
return $this

Types/Turtle/Scissor.ps1

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<#
2+
.SYNOPSIS
3+
Draws a Scissor
4+
.DESCRIPTION
5+
Draws a Scissor in turtle.
6+
7+
A Scissor is a pair of intersecting lines, drawn at an angle.
8+
.EXAMPLE
9+
Turtle Scissor Save ./Scissor.svg
10+
#>
11+
param(
12+
# The distance to travel
13+
[double]
14+
$Distance = 10,
15+
16+
# The interior angle of the scissors
17+
[double]
18+
$Angle = 60
19+
)
20+
21+
22+
$this.
23+
Rotate($angle). # Rotate
24+
Forward($distance). # Move Forward
25+
Rotate($angle * -2). # Rotate Back
26+
Forward($Distance). # Move Forward
27+
Rotate($Angle) # Rotate

0 commit comments

Comments
 (0)