Skip to content

Instantly share code, notes, and snippets.

@seivan
Last active August 29, 2015 14:02
Show Gist options
  • Select an option

  • Save seivan/9abd3876fd293bda01c4 to your computer and use it in GitHub Desktop.

Select an option

Save seivan/9abd3876fd293bda01c4 to your computer and use it in GitHub Desktop.
Vectoriah
//
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