Skip to content

Commit 35ca62c

Browse files
committed
Add CounterClockWise(CCW)
1 parent 65c199a commit 35ca62c

14 files changed

+264
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
CounterClockWise(CCW) Algorithm
3+
The user cross-multiplies corresponding coordinates to find the area encompassing the polygon,
4+
and subtracts it from the surrounding polygon to find the area of the polygon within.
5+
This code is based on the "Shoelace formula" by Carl Friedrich Gauss
6+
https://en.wikipedia.org/wiki/Shoelace_formula
7+
*/
8+
9+
import Foundation
10+
11+
// MARK : Point struct for defining 2-D coordinate(x,y)
12+
public struct Point{
13+
// Coordinate(x,y)
14+
var x: Int
15+
var y: Int
16+
17+
public init(x: Int ,y: Int){
18+
self.x = x
19+
self.y = y
20+
}
21+
}
22+
23+
// MARK : Function that determine the area of a simple polygon whose vertices are described
24+
// by their Cartesian coordinates in the plane.
25+
func ccw(points: [Point]) -> Int{
26+
let polygon = points.count
27+
var orientation = 0
28+
29+
// Take the first x-coordinate and multiply it by the second y-value,
30+
// then take the second x-coordinate and multiply it by the third y-value,
31+
// and repeat as many times until it is done for all wanted points.
32+
for i in 0..<polygon{
33+
orientation += (points[i%polygon].x*points[(i+1)%polygon].y
34+
- points[(i+1)%polygon].x*points[i%polygon].y)
35+
}
36+
37+
// If the points are labeled sequentially in the counterclockwise direction,
38+
// then the sum of the above determinants is positive and the absolute value signs can be omitted
39+
// if they are labeled in the clockwise direction, the sum of the determinants will be negative.
40+
// This is because the formula can be viewed as a special case of Green's Theorem.
41+
switch orientation {
42+
case Int.min..<0:
43+
return -1 // if operation < 0 : ClockWise
44+
case 0:
45+
return 0 // if operation == 0 : Parallel
46+
default:
47+
return 1 // if operation > 0 : CounterClockWise
48+
}
49+
}
50+
51+
// A few simple tests
52+
53+
54+
// Triangle
55+
var p1 = Point(x: 5, y: 8)
56+
var p2 = Point(x: 9, y: 1)
57+
var p3 = Point(x: 3, y: 6)
58+
59+
print(ccw(points: [p1,p2,p3])) // -1 means ClockWise
60+
61+
// Quadrilateral
62+
var p4 = Point(x: 5, y: 8)
63+
var p5 = Point(x: 2, y: 3)
64+
var p6 = Point(x: 6, y: 1)
65+
var p7 = Point(x: 9, y: 3)
66+
67+
print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise
68+
69+
// Pentagon
70+
var p8 = Point(x: 5, y: 11)
71+
var p9 = Point(x: 3, y: 4)
72+
var p10 = Point(x: 5, y: 6)
73+
var p11 = Point(x: 9, y: 5)
74+
var p12 = Point(x: 12, y: 8)
75+
76+
print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='ios' executeOnSourceChanges='false'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>

CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
CounterClockWise(CCW) Algorithm
3+
The user cross-multiplies corresponding coordinates to find the area encompassing the polygon,
4+
and subtracts it from the surrounding polygon to find the area of the polygon within.
5+
This code is based on the "Shoelace formula" by Carl Friedrich Gauss
6+
https://en.wikipedia.org/wiki/Shoelace_formula
7+
*/
8+
9+
10+
import Foundation
11+
12+
// MARK : Point struct for defining 2-D coordinate(x,y)
13+
public struct Point{
14+
// Coordinate(x,y)
15+
var x: Int
16+
var y: Int
17+
18+
public init(x: Int ,y: Int){
19+
self.x = x
20+
self.y = y
21+
}
22+
}
23+
24+
// MARK : Function that determine the area of a simple polygon whose vertices are described
25+
// by their Cartesian coordinates in the plane.
26+
func ccw(points: [Point]) -> Int{
27+
let polygon = points.count
28+
var orientation = 0
29+
30+
// Take the first x-coordinate and multiply it by the second y-value,
31+
// then take the second x-coordinate and multiply it by the third y-value,
32+
// and repeat as many times until it is done for all wanted points.
33+
for i in 0..<polygon{
34+
orientation += (points[i%polygon].x*points[(i+1)%polygon].y
35+
- points[(i+1)%polygon].x*points[i%polygon].y)
36+
}
37+
38+
// If the points are labeled sequentially in the counterclockwise direction,
39+
// then the sum of the above determinants is positive and the absolute value signs can be omitted
40+
// if they are labeled in the clockwise direction, the sum of the determinants will be negative.
41+
// This is because the formula can be viewed as a special case of Green's Theorem.
42+
switch orientation {
43+
case Int.min..<0:
44+
return -1 // if operation < 0 : ClockWise
45+
case 0:
46+
return 0 // if operation == 0 : Parallel
47+
default:
48+
return 1 // if operation > 0 : CounterClockWise
49+
}
50+
}
20.2 KB
Loading
8.87 KB
Loading

CounterClockWise/Images/Shoelace.png

75.5 KB
Loading
10.1 KB
Loading

CounterClockWise/Images/pentagon.png

24.7 KB
Loading
21.8 KB
Loading

CounterClockWise/Images/triangle.png

19.2 KB
Loading

CounterClockWise/README.md

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# CounterClockWise
2+
3+
Goal : Determine what direction to take when multiple points are given.
4+
5+
CounterClockWise(CCW) is based on [Shoelace formula](https://en.wikipedia.org/wiki/Shoelace_formula#Examples) by Carl Friedrich Gauss.
6+
7+
8+
9+
1. Take the first x-coordinate and multiply it by the second y-value, then take the second x-coordinate and multiply it by the third y-value, and repeat as many times until it is done for all wanted points.
10+
2. If the points are labeled sequentially in the counterclockwise direction, then the sum of the above determinants is positive and the absolute value signs can be omitted if they are labeled in the clockwise direction, the sum of the determinants will be negative. This is because the formula can be viewed as a special case of [Green's theorem](https://en.wikipedia.org/wiki/Green%27s_theorem).
11+
12+
![Shoelace](./Images/Shoelace.png)
13+
14+
15+
16+
Here's an implementation in Swift that should be easy to understand:
17+
18+
```swift
19+
func ccw(points: [Point]) -> Int{
20+
let polygon = points.count
21+
var orientation = 0
22+
23+
for i in 0..<polygon{
24+
orientation += (points[i%polygon].x*points[(i+1)%polygon].y
25+
- points[(i+1)%polygon].x*points[i%polygon].y)
26+
}
27+
28+
switch orientation {
29+
case Int.min..<0:
30+
return -1 // if operation < 0 : ClockWise
31+
case 0:
32+
return 0 // if operation == 0 : Parallel
33+
default:
34+
return 1 // if operation > 0 : CounterClockWise
35+
}
36+
}
37+
```
38+
39+
Put this code in a playground and test it like so:
40+
41+
```swift
42+
var p1 = Point(x: 5, y: 8)
43+
var p2 = Point(x: 9, y: 1)
44+
var p3 = Point(x: 3, y: 6)
45+
46+
print(ccw(points: [p1,p2,p3])) // -1 means ClockWise
47+
```
48+
49+
Here's how it works. When given an `[Photo]`, `ccw(points:)` calculates the direction of the given points according to the Shoelaces formula.
50+
51+
52+
53+
`orientation` is less than 0, the direction is clockwise.
54+
55+
`orientation` is equal to 0, the direction is parallel.
56+
57+
`orientation` is greater than 0, the direction is counterclockwise.
58+
59+
60+
61+
## An example
62+
63+
**In Triangle**
64+
65+
```swift
66+
var p1 = Point(x: 5, y: 8)
67+
var p2 = Point(x: 9, y: 1)
68+
var p3 = Point(x: 3, y: 6)
69+
70+
print(ccw(points: [p1,p2,p3])) // -1 means ClockWise
71+
```
72+
73+
![triangle](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Triangle_img.jpg)
74+
75+
![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/triangle.png)
76+
77+
78+
79+
**In Quadrilateral**
80+
81+
```swift
82+
var p4 = Point(x: 5, y: 8)
83+
var p5 = Point(x: 2, y: 3)
84+
var p6 = Point(x: 6, y: 1)
85+
var p7 = Point(x: 9, y: 3)
86+
87+
print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise
88+
```
89+
90+
![Quadrilateral](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Quadrilateral_img.jpg)
91+
92+
![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/quadrilateral.png)
93+
94+
95+
96+
**In Pentagon**
97+
98+
```swift
99+
var p8 = Point(x: 5, y: 11)
100+
var p9 = Point(x: 3, y: 4)
101+
var p10 = Point(x: 5, y: 6)
102+
var p11 = Point(x: 9, y: 5)
103+
var p12 = Point(x: 12, y: 8)
104+
105+
print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise
106+
```
107+
108+
![triangle](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Pentagon_img.png)
109+
110+
![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/pentagon.png)
111+
112+
113+
114+
You probably won't need to use the CCW in any real-world problems, but it's cool to play around with geometry algorithm. The formula was described by Meister (1724-1788) in 1769 and by Gauss in 1795. It can be verified by dividing the polygon into triangles, and can be considered to be a special case of Green's theorem.
115+
116+
117+
118+
*Written for Swift Algorithm Club by TaeJoong Yoon*

README.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ Bad sorting algorithms (don't use these!):
109109
- [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication.
110110
- [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere.
111111
- [Strassen's Multiplication Matrix](Strassen%20Matrix%20Multiplication/). Efficient way to handle matrix multiplication.
112+
- [CounterClockWise](/CounterClockWise/). Determining the area of a simple polygon.
112113

113114
### Machine learning
114115

0 commit comments

Comments
 (0)