/VectorExtensions

Vector data type enhancements for iOS development

Primary LanguageSwiftMIT LicenseMIT

VectorExtensions

Archive Notice

This repository is now archived. The algorithms in this Swift package are not performant and it is recommended that you use SIMDExtensions if you are looking for an explicitly typed way of doing vector arithmetic. SIMD is made easy with Apple's framework, and SIMDExtensions is an API that cuts down on the effort of reading through code documentation to figure out what c-style SIMD function will work with what SIMD types. It also includes utilities similar to the ones present in this project. This repository will remain here for educational purposes because it showcases the power of the protocol-oriented nature of Swift. This package is no longer used in FieldFab for iOS.

This Swift package enhances the functionality of the built in Vector data types for SceneKit and Core Graphics, making it much easier to work with procedurally generated 2D and 3D content. This package is also one of the many core components powering FieldFab for iOS.

If you do not want to extend the built in data types, but would like to roll your own Vector data types, see the VectorProtocol page. VectorExtensions depends upon VectorProtocol.

Features

  • Advanced mathematical functions integrated for CGPoint, SCNVector3, and SCNQuaternion using protocol composition, making the library extremely small and easy to maintain
  • Compiler flags that allow this package to be compiled for iOS or macOS, using the correct underlying data types
  • Euler and Spherical data types included in addition, making it easier to deal with vector rotations of different kinds
  • Code documentation that covers usage and allows for descriptive SourceKit LSP code completions in Xcode
  • XCTest suite included
  • Extensions to the BinaryFloatingPoint protocol with useful mathematical functions
  • VectorProtocol allows you to roll your own data types

Usage

FieldFab VectorExtensions implementation in action

With this swift package, working with procedurally generated 2D and 3D content is a piece of cake. Rather than converting to and from SIMD data types just to perform vector calculations, you can do all of them on the data types that SceneKit and CoreGraphics (or SpriteKit with CGPoint) use. The beauty is in the underlying VectorProtocol. Since many operations, such as working with scalars, normalizing, calculating distance, or testing for equality, are common among all Vector types, the math is pretty much the same. Rather than write enormous extensions for each type, they conform to a protocol with default implementations for each calculation, taking into account how many axes they store. This makes the code very easy to maintain.

Vector

Protocol which adds common functionality to any conforming Vector types

public protocol Vector: Equatable

Inheritance

Equatable

Properties and Methods

mutating func addScalar(scale s: BFP) Add scale to every axis

mutating func addScalar(_ s: BFP) Add scale to every axis

func addedScalar(scale s: BFP) -> Self Add scale to every axis and return new vector

func addedScalar(_ s: BFP) -> Self Add scale to every axis and return new vector

mutating func add(_ v: Self) Add some vector to this vector

func added(_ v: Self) -> Self Add some vector to this vector and return new vector

mutating func subScalar(scale s: BFP) Subtract scalar from every axis

mutating func subScalar(_ s: BFP) Subtract scalar from every axis

func subbedScalar(scale s: BFP) -> Self Subtract scalar from every axis and return new vector

func subbedScalar(_ s: BFP) -> Self Subtract scalar from every axis and return new vector

mutating func sub(_ v: Self) Subtract some vector from this vector

func subbed(_ v: Self) -> Self Subtract some vector from this vector and return new vector

mutating func multiplyScalar(scale s: BFP) Multiply scalar from every axis

mutating func multiplyScalar(_ s: BFP) Multiply scalar from every axis

func multipliedScalar(scale s: BFP) -> Self Multiply scalar from every axis and return new vector

func multipliedScalar(_ s: BFP) -> Self Multiply scalar from every axis and return new vector

mutating func multiply(_ v: Self) Multiply this vector by some vector

func multiplied(_ v: Self) -> Self Multiply this vector by some vector and return new vector

mutating func divideScalar(scale s: BFP) Divide scalar from every axis

mutating func divideScalar(_ s: BFP) Divide scalar from every axis

func dividedScalar(scale s: BFP) -> Self Divide scalar from every axis and return new vector

func dividedScalar(_ s: BFP) -> Self Divide scalar from every axis and return new vector

mutating func divide(_ v: Self) Divide this vector by some vector

func divided(_ v: Self) -> Self Divide this vector by some vector and return new vector

mutating func translate(coordinates c: [Axis: BFP]) Take a dictionary, where the keys are Axis and the values are BFP, and translate this Vector's axes by those values

mutating func translate(_ c: [Axis: BFP]) Take a dictionary, where the keys are Axis and the values are BFP, and translate this Vector's axes by those values

mutating func translate(_ v: Self) Translate this vector by the values of another vector

func translated(coordinates c: [Axis: BFP]) -> Self Take a dictionary, where the keys are Axis and the values are BFP, translate this Vector's axes by those values, and return new vector

func translated(_ c: [Axis: BFP]) -> Self Take a dictionary, where the keys are Axis and the values are BFP, and translate this Vector's axes by those values

func translated(_ v: Self) -> Self Translate this vector by the values of another vector and return new vector

mutating func flip(_ axis: Axis...) Variadic function for flipping, or inverting, each axis

func flipped(_ axis: Axis...) -> Self Variadic function for flipping, or inverting, each axis, then returning new vector

mutating func zero(_ axis: Axis...) Zero out selected axes

func zeroed(_ axis: Axis...) -> Self Zero out selected axes and return new vector

mutating func floor() Floor the value of each axis

func floored() -> Self Floor the value of each axis and return new vector

mutating func ceil() Ceil the value of each axis

func ceiled() -> Self Ceil the value of each axis and return new vector

mutating func round() Round each axis using schoolbook rounding (to nearest whole number)

func rounded() -> Self Round each axis using schoolbook rounding (to nearest whole number) and return result

mutating func round(to: BFP) Round each axis to the nearest BFP

func rounded(to: BFP) -> Self Round each axis to the nearest BFP and return result

mutating func roundToZero() Round each axis towards zero

func roundedToZero() -> Self Round each axis towards zero and return result

func distanceSquared(_ to: Self) -> BFP Get the distance between two vectors

func distance(_ to: Self) -> BFP Get the distance between two vectors ( precise )

func manhattanDistance(_ to: Self) -> BFP Get the distance between two vectors at each whole step, one direction at a time (like traversing city blocks)

var lengthSquared: BFP Get the length

var length: BFP Get the length ( precise )

var manhattanLength: BFP Get the length from Zero at each whole step, one direction at a time

func dotProduct(_ v: Self) -> BFP Get the dot product of two vectors

func crossProduct(_ v: Self) -> BFP Get the cross product of two vectors

mutating func normalize() Normalize the vector

func normalized() -> Self Normalize and return new vector

static func + (l: Self, r: Self) -> Self Add two vectors together and return result

static func - (l: Self, r: Self) -> Self Subtract two vectors from each other and return result

static func * (l: Self, r: Self) -> Self Multiply two vectors together and return result

static func / (l: Self, r: Self) -> Self Divide two vectors and return result

static func += (l: inout Self, r: Self) Add a vector to this vector

static func -= (l: inout Self, r: Self) Subtract a vector from this vector

static func *= (l: inout Self, r: Self) Multiply this vector by another vector

static func /= (l: inout Self, r: Self) Divide this vector by another vector

static func + (l: Self, r: BFP) Add a scalar to this vector and return result

static func - (l: Self, r: BFP) Subtract a scalar from this vector and return result

static func * (l: Self, r: BFP) Multiply this vector by a scalar and return result

static func / (l: Self, r: BFP) Divide this vector by a scalar and return result

static func += (l: inout Self, r: BFP) { l.addScalar(r) } Add a scalar to this vector

static func -= (l: inout Self, r: BFP) { l.subScalar(r) } Subtract a scalar from this vector

static func *= (l: inout Self, r: BFP) { l.multiplyScalar(r) } Multiply this vector by a scalar

static func /= (l: inout Self, r: BFP) { l.divideScalar(r == 0 ? 1 : r) } Divide this vector by a scalar

static prefix func - (v: Self) -> Self Invert all axes of this vector and return result