diff --git a/CounterClockWise/CounterClockWise.playground/Contents.swift b/CounterClockWise/CounterClockWise.playground/Contents.swift new file mode 100644 index 000000000..ffa91ecbb --- /dev/null +++ b/CounterClockWise/CounterClockWise.playground/Contents.swift @@ -0,0 +1,76 @@ +/* + CounterClockWise(CCW) Algorithm + The user cross-multiplies corresponding coordinates to find the area encompassing the polygon, + and subtracts it from the surrounding polygon to find the area of the polygon within. + This code is based on the "Shoelace formula" by Carl Friedrich Gauss + https://en.wikipedia.org/wiki/Shoelace_formula + */ + +import Foundation + +// MARK : Point struct for defining 2-D coordinate(x,y) +public struct Point{ + // Coordinate(x,y) + var x: Int + var y: Int + + public init(x: Int ,y: Int){ + self.x = x + self.y = y + } +} + +// MARK : Function that determine the area of a simple polygon whose vertices are described +// by their Cartesian coordinates in the plane. +func ccw(points: [Point]) -> Int{ + let polygon = points.count + var orientation = 0 + + // 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. + for i in 0.. 0 : CounterClockWise + } +} + +// A few simple tests + + +// Triangle +var p1 = Point(x: 5, y: 8) +var p2 = Point(x: 9, y: 1) +var p3 = Point(x: 3, y: 6) + +print(ccw(points: [p1,p2,p3])) // -1 means ClockWise + +// Quadrilateral +var p4 = Point(x: 5, y: 8) +var p5 = Point(x: 2, y: 3) +var p6 = Point(x: 6, y: 1) +var p7 = Point(x: 9, y: 3) + +print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise + +// Pentagon +var p8 = Point(x: 5, y: 11) +var p9 = Point(x: 3, y: 4) +var p10 = Point(x: 5, y: 6) +var p11 = Point(x: 9, y: 5) +var p12 = Point(x: 12, y: 8) + +print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise diff --git a/CounterClockWise/CounterClockWise.playground/contents.xcplayground b/CounterClockWise/CounterClockWise.playground/contents.xcplayground new file mode 100644 index 000000000..9f5f2f40c --- /dev/null +++ b/CounterClockWise/CounterClockWise.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata b/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/CounterClockWise/CounterClockWise.swift b/CounterClockWise/CounterClockWise.swift new file mode 100644 index 000000000..07c422ea5 --- /dev/null +++ b/CounterClockWise/CounterClockWise.swift @@ -0,0 +1,50 @@ +/* + CounterClockWise(CCW) Algorithm + The user cross-multiplies corresponding coordinates to find the area encompassing the polygon, + and subtracts it from the surrounding polygon to find the area of the polygon within. + This code is based on the "Shoelace formula" by Carl Friedrich Gauss + https://en.wikipedia.org/wiki/Shoelace_formula + */ + + +import Foundation + +// MARK : Point struct for defining 2-D coordinate(x,y) +public struct Point{ + // Coordinate(x,y) + var x: Int + var y: Int + + public init(x: Int ,y: Int){ + self.x = x + self.y = y + } +} + +// MARK : Function that determine the area of a simple polygon whose vertices are described +// by their Cartesian coordinates in the plane. +func ccw(points: [Point]) -> Int{ + let polygon = points.count + var orientation = 0 + + // 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. + for i in 0.. 0 : CounterClockWise + } +} diff --git a/CounterClockWise/Images/Pentagon_img.png b/CounterClockWise/Images/Pentagon_img.png new file mode 100644 index 000000000..44d858303 Binary files /dev/null and b/CounterClockWise/Images/Pentagon_img.png differ diff --git a/CounterClockWise/Images/Quadrilateral_img.jpg b/CounterClockWise/Images/Quadrilateral_img.jpg new file mode 100644 index 000000000..b48d7ee5a Binary files /dev/null and b/CounterClockWise/Images/Quadrilateral_img.jpg differ diff --git a/CounterClockWise/Images/Shoelace.png b/CounterClockWise/Images/Shoelace.png new file mode 100644 index 000000000..2691ec129 Binary files /dev/null and b/CounterClockWise/Images/Shoelace.png differ diff --git a/CounterClockWise/Images/Triangle_img.jpg b/CounterClockWise/Images/Triangle_img.jpg new file mode 100644 index 000000000..8a010ca15 Binary files /dev/null and b/CounterClockWise/Images/Triangle_img.jpg differ diff --git a/CounterClockWise/Images/pentagon.png b/CounterClockWise/Images/pentagon.png new file mode 100644 index 000000000..063c77900 Binary files /dev/null and b/CounterClockWise/Images/pentagon.png differ diff --git a/CounterClockWise/Images/quadrilateral.png b/CounterClockWise/Images/quadrilateral.png new file mode 100644 index 000000000..139d09778 Binary files /dev/null and b/CounterClockWise/Images/quadrilateral.png differ diff --git a/CounterClockWise/Images/triangle.png b/CounterClockWise/Images/triangle.png new file mode 100644 index 000000000..67e8b453f Binary files /dev/null and b/CounterClockWise/Images/triangle.png differ diff --git a/CounterClockWise/README.md b/CounterClockWise/README.md new file mode 100644 index 000000000..2d15eba53 --- /dev/null +++ b/CounterClockWise/README.md @@ -0,0 +1,118 @@ +# CounterClockWise + +Goal : Determine what direction to take when multiple points are given. + +CounterClockWise(CCW) is based on [Shoelace formula](https://en.wikipedia.org/wiki/Shoelace_formula#Examples) by Carl Friedrich Gauss. + + + +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. +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). + +![Shoelace](./Images/Shoelace.png) + + + +Here's an implementation in Swift that should be easy to understand: + +```swift +func ccw(points: [Point]) -> Int{ + let polygon = points.count + var orientation = 0 + + for i in 0.. 0 : CounterClockWise + } +} +``` + +Put this code in a playground and test it like so: + +```swift +var p1 = Point(x: 5, y: 8) +var p2 = Point(x: 9, y: 1) +var p3 = Point(x: 3, y: 6) + +print(ccw(points: [p1,p2,p3])) // -1 means ClockWise +``` + +Here's how it works. When given an `[Photo]`, `ccw(points:)` calculates the direction of the given points according to the Shoelaces formula. + + + +`orientation` is less than 0, the direction is clockwise. + +`orientation` is equal to 0, the direction is parallel. + +`orientation` is greater than 0, the direction is counterclockwise. + + + +## An example + +**In Triangle** + +```swift +var p1 = Point(x: 5, y: 8) +var p2 = Point(x: 9, y: 1) +var p3 = Point(x: 3, y: 6) + +print(ccw(points: [p1,p2,p3])) // -1 means ClockWise +``` + +![triangle](./Images/Triangle_img.jpg) + +![triangleExpression](./Images/triangle.png) + + + +**In Quadrilateral** + +```swift +var p4 = Point(x: 5, y: 8) +var p5 = Point(x: 2, y: 3) +var p6 = Point(x: 6, y: 1) +var p7 = Point(x: 9, y: 3) + +print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise +``` + +![Quadrilateral](./Images/Quadrilateral_img.jpg) + +![triangleExpression](./Images/quadrilateral.png) + + + +**In Pentagon** + +```swift +var p8 = Point(x: 5, y: 11) +var p9 = Point(x: 3, y: 4) +var p10 = Point(x: 5, y: 6) +var p11 = Point(x: 9, y: 5) +var p12 = Point(x: 12, y: 8) + +print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise +``` + +![triangle](./Images/Pentagon_img.png) + +![triangleExpression](./Images/pentagon.png) + + + +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. + + + +*Written for Swift Algorithm Club by TaeJoong Yoon* diff --git a/README.markdown b/README.markdown index e87fe0335..fbcde7c86 100644 --- a/README.markdown +++ b/README.markdown @@ -110,6 +110,7 @@ Bad sorting algorithms (don't use these!): - [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication. - [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. - [Strassen's Multiplication Matrix](Strassen%20Matrix%20Multiplication/). Efficient way to handle matrix multiplication. +- [CounterClockWise](/CounterClockWise/). Determining the area of a simple polygon. ### Machine learning