Skip to content

Commit 6afc516

Browse files
feat: Turtle.Morph() ( Fixes #154 )
1 parent 250eb66 commit 6afc516

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

Types/Turtle/Morph.ps1

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<#
2+
.SYNOPSIS
3+
Morphs a Turtle
4+
.DESCRIPTION
5+
Morphs a Turtle by animating its path.
6+
7+
Any two paths with the same number of points can be morphed into each other.
8+
.EXAMPLE
9+
$sierpinskiTriangle = turtle SierpinskiTriangle 42 4
10+
$SierpinskiTriangleFlipped = turtle rotate 180 SierpinskiTriangle 42 4
11+
turtle SierpinskiTriangle 42 4 morph (
12+
$SierpinskiTriangle,
13+
$SierpinskiTriangleFlipped,
14+
$sierpinskiTriangle
15+
) save ./SierpinskiTriangleFlip.svg
16+
.EXAMPLE
17+
$sideCount = (3..24 | Get-Random )
18+
$stepCount = 36
19+
20+
$flower = turtle rotate ((Get-Random -Max 180) * -1) flower 42 10 $sideCount $stepCount
21+
$flower2 = turtle rotate ((Get-Random -Max 180)) flower 42 50 $sideCount $stepCount
22+
$flower3 = turtle rotate ((Get-Random -Max 90)) flower 42 20 $sideCount $stepCount
23+
turtle flower 42 10 $sideCount $stepCount duration ($sideCount * 3) morph ($flower, $flower2,$flower) |
24+
save-turtle ./flowerMorph.svg Pattern
25+
.EXAMPLE
26+
$flowerAngle = (40..60 | Get-Random )
27+
$stepCount = 36
28+
$radius = 23..42 | Get-Random
29+
30+
$flowerPetals = turtle rotate ((Get-Random -Max 180) * -1) flowerPetal $radius 10 $flowerAngle $stepCount
31+
$flowerPetals3 = turtle rotate ((Get-Random -Max 180)) flowerPetal $radius 40 $flowerAngle $stepCount
32+
turtle flowerPetal $radius 10 $flowerAngle $stepCount duration $radius morph (
33+
$flowerPetals,
34+
$flowerPetals3,
35+
$flowerPetals
36+
) | Save-Turtle ./flowerPetalMorph.svg Pattern
37+
#>
38+
param(
39+
[Parameter(ValueFromRemainingArguments)]
40+
$Arguments
41+
)
42+
43+
$durationArgument = $null
44+
45+
$newPaths = @(foreach ($arg in $Arguments) {
46+
if ($arg -is [string]) {
47+
if ($arg -match '^\s{0,}m') {
48+
$arg
49+
}
50+
} elseif ($arg.PathData) {
51+
$arg.PathData
52+
} elseif ($arg.D) {
53+
$arg.D
54+
} elseif ($arg -is [TimeSpan]) {
55+
$durationArgument = $arg
56+
}
57+
elseif ($arg -is [double] -or $arg -is [int]) {
58+
$durationArgument = [TimeSpan]::FromSeconds($arg)
59+
}
60+
})
61+
62+
if (-not $newPaths) {
63+
return $this
64+
<#$pathSegments = @($this.PathData -split '(?=\p{L})')
65+
$newPaths = @(for ($segmentNumber = 0; $segmentNumber -lt $pathSegments.Count; $segmentNumber++) {
66+
$pathSegments[0..$segmentNumber] -join ' '
67+
}) -join ';'#>
68+
}
69+
70+
if ($this.PathAnimation) {
71+
$updatedAnimations =
72+
@(foreach ($animationXML in $this.PathAnimation -split '(?<=/>)') {
73+
$animationXML = $animationXML -as [xml]
74+
if (-not $animationXML) { continue }
75+
if ($animationXML.attributeName -eq 'd') {
76+
$animationXML.values = "$($newPaths -join ';')"
77+
}
78+
$animationXML.OuterXml
79+
})
80+
$this.PathAnimation = $updatedAnimations
81+
} else {
82+
$this.PathAnimation += [Ordered]@{
83+
attributeName = 'd' ; values = "$($newPaths -join ';')" ; repeatCount = 'indefinite'; dur = $(
84+
if ($durationArgument) {
85+
"$($durationArgument.TotalSeconds)s"
86+
} elseif ($this.Duration) {
87+
"$($this.Duration.TotalSeconds)s"
88+
} else {
89+
"4.2s"
90+
}
91+
92+
)
93+
}
94+
}
95+
96+
return $this

0 commit comments

Comments
 (0)