Last active
August 29, 2015 14:02
-
-
Save seivan/9abd3876fd293bda01c4 to your computer and use it in GitHub Desktop.
Vectoriah
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| import Foundation | |
| //import Cocoa | |
| //import SpriteKit | |
| //import XCPlayground | |
| protocol VectorOperatable { | |
| class func create(#horizontal:CGFloat,vertical:CGFloat) -> Self | |
| var horizontal:CGFloat { get set } | |
| var vertical:CGFloat { get set } | |
| } | |
| protocol VectorCalculating:VectorOperatable { | |
| var angleInRadians:CGFloat {get} | |
| var magnitude:CGFloat {get} | |
| var length:CGFloat {get} | |
| var normalized:Self {get} | |
| func dotProduct <T : VectorCalculating>(point:T) -> CGFloat | |
| func limit(value:CGFloat) -> Self | |
| func distanceTo<T : VectorCalculating> (endPoint:T) -> CGFloat | |
| func scale(value:CGFloat) -> Self | |
| func angledVector(value:CGFloat) -> Self | |
| } | |
| @infix func - <T : VectorOperatable, U : VectorOperatable>(lhs: T, rhs:U) -> T { | |
| return T.create(horizontal: lhs.horizontal-rhs.horizontal, vertical: lhs.vertical-rhs.vertical) | |
| } | |
| @infix func -= <T : VectorOperatable, U : VectorOperatable>(inout lhs: T, rhs:U) { | |
| lhs = lhs - rhs | |
| } | |
| @infix func + <T : VectorOperatable, U : VectorOperatable>(lhs: T, rhs:U) -> T { | |
| return T.create(horizontal: lhs.horizontal+rhs.horizontal, vertical: lhs.vertical+rhs.vertical) | |
| } | |
| @infix func += <T : VectorOperatable, U : VectorOperatable>(inout lhs: T, rhs:U) { | |
| lhs = lhs + rhs | |
| } | |
| @infix func * <T : VectorOperatable, U : VectorOperatable>(lhs: T, rhs:U) -> T { | |
| return T.create(horizontal: lhs.horizontal*rhs.horizontal, vertical: lhs.vertical*rhs.vertical); | |
| } | |
| @infix func *= <T : VectorOperatable, U : VectorOperatable>(inout lhs: T, rhs:U) { | |
| lhs = lhs * rhs | |
| } | |
| @infix func * <T : VectorOperatable>(lhs: T, scalar:CGFloat) -> T { | |
| return T.create(horizontal: lhs.horizontal*scalar, vertical: lhs.vertical*scalar) | |
| } | |
| @infix func *= <T : VectorOperatable>(inout lhs: T, value:CGFloat) { | |
| lhs = lhs * value | |
| } | |
| @infix func / <T : VectorOperatable>(lhs: T, scalar:CGFloat) -> T { | |
| return T.create(horizontal: lhs.horizontal/scalar, vertical: lhs.vertical/scalar); | |
| } | |
| @infix func /= <T : VectorOperatable>(inout lhs: T, scalar:CGFloat) -> T { | |
| lhs = lhs / scalar | |
| return lhs | |
| } | |
| struct VectorArithmetic { | |
| static func angleInRadians <T : VectorCalculating>(lhs:T) -> CGFloat { | |
| let normalized = lhs.normalized | |
| let theta = atan2(normalized.vertical, normalized.horizontal) | |
| return theta + M_PI_2 * -1 | |
| } | |
| static func magnitude <T : VectorCalculating>(lhs:T) -> CGFloat { | |
| return sqrt(lhs.dotProduct(lhs)) | |
| } | |
| static func reversed <T : VectorCalculating>(lhs:T) -> T { | |
| return lhs * -1 | |
| } | |
| static func dotProduct <T : VectorOperatable, U : VectorOperatable > (lhs:T, rhs:U) -> CGFloat { | |
| return (lhs.horizontal*rhs.horizontal) + (lhs.vertical*rhs.vertical) | |
| } | |
| static func normalized <T : VectorCalculating>(lhs:T) -> T { | |
| let length = lhs.length | |
| var newPoint:T = lhs | |
| if(length > 0.0) { | |
| newPoint /= length | |
| } | |
| return newPoint | |
| } | |
| static func limit <T : VectorCalculating>(lhs:T, value:CGFloat) -> T { | |
| var newPoint = lhs | |
| if(lhs.magnitude > value) { | |
| newPoint = newPoint.normalized * value | |
| } | |
| return newPoint | |
| } | |
| static func distanceTo <T : VectorCalculating, U : VectorCalculating > (lhs:T, rhs:U) -> CGFloat { | |
| var deltaX = CGFloat.abs(lhs.horizontal - rhs.horizontal) | |
| var deltaY = CGFloat.abs(lhs.vertical - rhs.vertical) | |
| return T.create(horizontal: deltaX, vertical: deltaY).magnitude | |
| } | |
| static func scale <T : VectorCalculating>(lhs:T, value:CGFloat) -> T { | |
| return lhs.normalized * value | |
| } | |
| static func angledVector <T : VectorCalculating>(lhs:T, value:CGFloat) -> T { | |
| let length = lhs.length | |
| let vector = T.create(horizontal: cos(value) * length, vertical: sin(value) * length) | |
| return vector | |
| } | |
| } | |
| extension CGPoint: VectorCalculating { | |
| static func create(#horizontal:CGFloat,vertical:CGFloat) -> CGPoint { | |
| return CGPoint(x: horizontal, y: vertical) | |
| } | |
| var horizontal:CGFloat { | |
| get { return self.x } | |
| set { self.x = newValue } | |
| } | |
| var vertical:CGFloat { | |
| get { return self.y } | |
| set { self.y = newValue } | |
| } | |
| var angleInRadians:CGFloat { | |
| return VectorArithmetic.angleInRadians(self) | |
| } | |
| var magnitude:CGFloat { | |
| return VectorArithmetic.magnitude(self) | |
| } | |
| var length:CGFloat { | |
| return self.magnitude | |
| } | |
| func dotProduct <T : VectorCalculating> (point:T) -> CGFloat { | |
| return VectorArithmetic.dotProduct(self, rhs: point) | |
| } | |
| var normalized:CGPoint { | |
| return VectorArithmetic.normalized(self) | |
| } | |
| func limit(value:CGFloat) -> CGPoint { | |
| return VectorArithmetic.limit(self, value: value) | |
| } | |
| func distanceTo <T : VectorCalculating> (endPoint:T) -> CGFloat { | |
| return VectorArithmetic.distanceTo(self, rhs: endPoint) | |
| } | |
| func scale(value:CGFloat) -> CGPoint { | |
| return VectorArithmetic.scale(self, value: value) | |
| } | |
| func angledVector(value:CGFloat) -> CGPoint { | |
| return VectorArithmetic.angledVector(self, value: value) | |
| } | |
| } | |
| extension CGSize: VectorCalculating { | |
| static func create(#horizontal:CGFloat,vertical:CGFloat) -> CGSize { | |
| return CGSize(width: horizontal, height: vertical) | |
| } | |
| var horizontal:CGFloat { | |
| get { | |
| return self.width | |
| } | |
| set { | |
| self.width = newValue | |
| } | |
| } | |
| var vertical:CGFloat { | |
| get { | |
| return self.height | |
| } | |
| set { | |
| self.height = newValue | |
| } | |
| } | |
| var angleInRadians:CGFloat { | |
| return VectorArithmetic.angleInRadians(self) | |
| } | |
| var magnitude:CGFloat { | |
| return VectorArithmetic.magnitude(self) | |
| } | |
| var length:CGFloat { | |
| return self.magnitude | |
| } | |
| func dotProduct <T : VectorCalculating> (point:T) -> CGFloat { | |
| return VectorArithmetic.dotProduct(self, rhs: point) | |
| } | |
| var normalized:CGSize { | |
| return VectorArithmetic.normalized(self) | |
| } | |
| func limit(value:CGFloat) -> CGSize { | |
| return VectorArithmetic.limit(self, value: value) | |
| } | |
| func distanceTo <T : VectorCalculating> (endPoint:T) -> CGFloat { | |
| return VectorArithmetic.distanceTo(self, rhs: endPoint) | |
| } | |
| func scale(value:CGFloat) -> CGSize { | |
| return VectorArithmetic.scale(self, value: value) | |
| } | |
| func angledVector(value:CGFloat) -> CGSize { | |
| return VectorArithmetic.angledVector(self, value: value) | |
| } | |
| } | |
| let x = CGPoint(x: 50, y: 50) - CGSize(width: 20, height: 20) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment