Skip to content

Commit 2fe57fa

Browse files
authored
Add Convex Hull in PowerShell (TheRenegadeCoder#4859)
1 parent 55d91f8 commit 2fe57fa

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
function Show-Usage() {
2+
Write-Host 'Usage: please provide at least 3 x and y coordinates as separate lists (e.g. "100, 440, 210")'
3+
Exit 1
4+
}
5+
6+
function Parse-IntList([string]$Str) {
7+
@($Str.Split(",") | ForEach-Object { [int]::Parse($_) })
8+
}
9+
10+
class Point {
11+
[int]$X
12+
[int]$Y
13+
14+
Point([int]$x, [int]$y) {
15+
$this.X = $x
16+
$this.Y = $y
17+
}
18+
19+
[string] ToString() {
20+
return "($($this.X), $($this.Y))"
21+
}
22+
}
23+
24+
function Get-Points([int[]]$X, [int[]]$Y) {
25+
@(0..($X.Length - 1) | ForEach-Object { [Point]::new($X[$_], $Y[$_]) })
26+
}
27+
28+
# Find Convex Hull using Jarvis' algorithm
29+
# Source: https://www.geeksforgeeks.org/convex-hull-using-jarvis-algorithm-or-wrapping/
30+
function Invoke-ConvexHull([Point[]]$Points) {
31+
$n = $Points.Length
32+
33+
# The first point is the leftmost point with the highest y-coord in the event of a tie
34+
$l = Find-LeftmostPoint $Points
35+
36+
# Repeat until wrapped around to first hull point
37+
$p = $l
38+
do {
39+
# Output convex hull point
40+
$Points[$p]
41+
42+
$q = ($p + 1) % $n
43+
for ($j = 0; $j -lt $n; $j++) {
44+
# If point j is more counter-clockwise, then update end point (q)
45+
if ((Get-Orientation $Points[$p] $Points[$j] $Points[$q]) -lt 0) {
46+
$q = $j
47+
}
48+
}
49+
50+
$p = $q
51+
} while ($p -ne $l)
52+
}
53+
54+
function Find-LeftmostPoint([Point[]]$Points) {
55+
$leftmostPoint = [Point]::new([int]::MaxValue, [int]::MinValue)
56+
$leftmostIndex = 0
57+
for ($i = 0; $i -lt $Points.Length; $i++) {
58+
# In the event of a tie, pick the point with the greater y-coord
59+
if ($Points[$i].X -lt $leftmostPoint.X -or
60+
($Points[$i].X -eq $leftmostPoint.X -and $Points[$i].Y -gt $leftmostPoint.Y)
61+
) {
62+
$leftmostPoint = $Points[$i]
63+
$leftmostIndex = $i
64+
}
65+
}
66+
67+
$leftmostIndex
68+
}
69+
70+
# Get orientation of three points
71+
#
72+
# 0 = points are in a line
73+
# > 0 = points are clockwise
74+
# < 0 = points are counter-clockwise
75+
function Get-Orientation([Point]$P, [Point]$Q, [Point]$R) {
76+
($Q.Y - $P.Y) * ($R.X - $Q.X) - ($Q.X - $P.X) * ($R.Y - $Q.Y)
77+
}
78+
79+
if ($args.Length -lt 2 -or -not $args[0] -or -not $args[1]) {
80+
Show-Usage
81+
}
82+
83+
try {
84+
$x = Parse-IntList $args[0]
85+
$y = Parse-IntList $args[1]
86+
if ($x.Length -ne $y.Length -or $x.Length -lt 3) {
87+
Show-Usage
88+
}
89+
} catch {
90+
Show-Usage
91+
}
92+
93+
# Combine values into set of points
94+
$points = Get-Points $X $Y
95+
96+
# Get convex hull of points and show them
97+
$hullPoints = Invoke-ConvexHull $points
98+
Write-Output ($hullPoints -join "`n")

0 commit comments

Comments
 (0)