-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathConvexHullScanUsingGrahamScan.kt
97 lines (85 loc) · 2.36 KB
/
ConvexHullScanUsingGrahamScan.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package algorithmsinanutshell
import algorithmdesignmanualbook.print
import utils.PrintUtils
import utils.assertArraysSame
import java.util.*
private fun <T> Stack<T>.fromTopNext() = this[this.lastIndex - 1]
/**
* Find Convex Hull - a polygon that surrounds all points
*
* [link](https://www.cs.auckland.ac.nz/software/AlgAnim/convex_hull.html)
*/
class ConvexHullScanUsingGrahamScan(private val points: Array<Point>) {
private val result = Stack<Point>()
init {
require(points.size >= 3)
// Left most point is at 0th index
points.sortBy { it.x }
points.forEach(::println)
}
/**
* When LTR, exclude 2nd point
*
* When RTL, dont exclude
*
* ________x
*
* x
*
* /
*
* x
*
* Include all if ß12 = ß23
* x----- x ------x
*
*/
private fun excludeP2FromConvexHull(p1: Point, p2: Point, p3: Point): Boolean {
val orientation = OrientationOf3Points(p1, p2, p3)
return when (orientation.getOrientation()) {
Orientation.CW -> true
Orientation.ACW -> false
Orientation.COLINEAR -> false
}
}
fun execute(): Stack<Point> {
// Add first three points
result.add(points[0])
result.add(points[1])
result.add(points[2])
for (i in 3..points.lastIndex) {
val p3 = points[i]
// Last two from stack
var p2 = result.lastElement()
var p1 = result.fromTopNext()
while (excludeP2FromConvexHull(p1, p2, p3)) {
// pop the last element from stack and update p2 & p1. p3 remains the same
result.pop()
p2 = result.lastElement()
p1 = result.fromTopNext()
}
result.push(p3)
}
result.add(points[0])
println("Stack Content:")
result.forEach(::println)
return result
}
}
fun main() {
val exec = ConvexHullScanUsingGrahamScan(
arrayOf(
0 fromTo 3,
2 fromTo 3,
1 fromTo 1,
2 fromTo 1,
3 fromTo 0,
0 fromTo 0,
3 fromTo 3,
)
)
assertArraysSame(
expected = arrayOf(0 fromTo 3, 0 fromTo 0, 3 fromTo 0, 3 fromTo 3, 0 fromTo 3),
actual = exec.execute().toArray()
)
}