Skip to content

Instantly share code, notes, and snippets.

@gabrieloc
Last active January 25, 2021 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabrieloc/09da43092e63c7f129be716df3d50ef0 to your computer and use it in GitHub Desktop.
Save gabrieloc/09da43092e63c7f129be716df3d50ef0 to your computer and use it in GitHub Desktop.
Coerce core graphics types into generic vectors
import UIKit
protocol Vector {
associatedtype Primitive: FloatingPoint
var components: [Primitive] { get }
init(components: [Primitive])
}
extension CGPoint: Vector {
var components: [CGFloat] { [x, y] }
init(components: [CGFloat]) {
self.init(
x: components[safe: 0] ?? 0,
y: components[safe: 1] ?? 0
)
}
}
extension CGSize: Vector {
var components: [CGFloat] { [width, height] }
init(components: [CGFloat]) {
self.init(
width: components[safe: 0] ?? 0,
height: components[safe: 1] ?? 0
)
}
}
extension CGRect: Vector {
var components: [CGFloat] { [minX, minY, width, height] }
init(components: [CGFloat]) {
self.init(
x: components[safe: 0] ?? 0,
y: components[safe: 1] ?? 0,
width: components[safe: 2] ?? 0,
height: components[safe: 3] ?? 0
)
}
}
extension Vector {
static func * <V: Vector>(lhs: Self, rhs: V) -> Self where V.Primitive == Self.Primitive {
Self(components: lhs.components * rhs.components)
}
static var length: Int {
Self(components: []).components.count
}
static var one: Self {
Self(components: .init(repeating: 1, count: length))
}
}
extension Array where Element: Numeric {
static func * (lhs: Self, rhs: Self) -> Self {
let size = Swift.max(lhs.count, rhs.count)
return zip(lhs.withSize(size), rhs.withSize(size)).map { $0 * $1 }
}
func withSize(_ size: Int) -> Self {
(0..<size).map { $0 < count ? self[$0] : 0 }
}
subscript(safe index: Index) -> Element? {
indices.contains(index) ? self[index] : nil
}
}
// Examples
let point = CGPoint(x: 1, y: 2) * CGSize(width: 3, height: 4) // CGPoint x: 3, y: 8
let size = CGSize(width: 2, height: 2) * CGPoint.one // CGSize w: 2, h: 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment