MathEnhancer is a Swift package that provides extensions to the Swift math library. It includes a range of useful math functions and utility methods that expand upon the functionality of the Swift core library.
CGFloat
and Double
.CGFloat
and Double
.CGLine
.CGSize
, including addition, subtraction, multiplication, and division.CGPoint
, including distance calculations, colinearity checks, and arithmetic operations.To use MathEnhancer in your Swift project, simply add it as a dependency in your Package.swift
file:
swift
dependencies: [
.package(url: "https://github.com/Iliasnolsson/MathEnhancer", from: "1.0.0"..<"2.0.0")
]
After adding the package, you can import it into your Swift file and use it with the standard CGPoint
, CGSize
, and CGFloat
types:
swift
import MathEnhancer
// Using the `+` operator on a `CGPoint`
let pointA = CGPoint(x: 10, y: 20)
let pointB = CGPoint(x: 5, y: 10)
let sum = pointA + pointB // CGPoint(x: 15, y: 30)
// Using the `*` operator on a `CGSize`
let sizeA = CGSize(width: 10, height: 20)
let sizeB = CGSize(width: 2, height: 3)
let product = sizeA * sizeB // CGSize(width: 20, height: 60)
// Using the `-` operator on a `CGFloat`
let floatA: CGFloat = 10.0
let floatB: CGFloat = 5.0
let difference = floatA - floatB // 5.0
MathEnhancer adds the Operable
protocol and several extensions to common types, including:
Int
CGFloat
Float
Double
CGPoint
CGSize
MathEnhancer makes it easy to perform mathematical operations on CGPoint
, CGSize
, and CGFloat
types. Here are some examples of how you can use the package to simplify your code:
import MathEnhancer
// Interpolating between two `CGPoint` values
let pointA = CGPoint(x: 10, y: 20)
let pointB = CGPoint(x: 50, y: 100)
let interpolatedPoint = pointA.interpolateTo(pointB, amount: 0.5) // CGPoint(x: 30, y: 60)
// Scaling a `CGSize` to fit inside another `CGSize`
let sizeA = CGSize(width: 100, height: 200)
let sizeB = CGSize(width: 50, height: 50)
let scale = sizeA.scaleThatFits(sizeB) // 0.25
// Adding a `CGFloat` to a `CGSize` or `CGPoint`
let pointA = CGPoint(x: 10, y: 20)
let sizeA = CGSize(width: 50, height: 100)
let addedPoint = pointA +| 5 // CGPoint(x: 10, y: 25)
let addedSize = sizeA +| 10 // CGSize(width: 50, height: 110)
// Subtracting a `CGFloat` from a `CGSize` or `CGPoint`
let pointA = CGPoint(x: 10, y: 20)
let sizeA = CGSize(width: 50, height: 100)
let subtractedPoint = pointA +- 5 // CGPoint(x: 15, y: 20)
let subtractedSize = sizeA *- 0.5 // CGSize(width: 25, height: 50)
In addition to the above examples, MathEnhancer also provides an Operable
protocol, which allows you to perform mathematical operations on custom types as well. Here's an example of how you can use Operable
to extend
Operable
MathEnhancer can be extended to support additional types as well. For example, let's say you have a custom Vector2D
struct:
struct Vector2D {
var x: CGFloat
var y: CGFloat
}
You can make Vector2D
operable by extending it to conform to Operable
:
extension Vector2D: Operable {
static func +(left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
static func -(left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x - right.x, y: left.y - right.y)
}
static func *(left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x * right.x, y: left.y * right.y)
}
static func /(left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x / right.x, y: left.y / right.y)
}
}
You can now use +
, -
, *
, and /
on Vector2D
objects:
let vectorA = Vector2D(x: 2.0, y: 4.0)
let vectorB = Vector2D(x: 3.0, y: 6.0)
let vectorC = vectorA + vectorB
Operable
In addition to the standard mathematical operations provided by Operable
, you can also extend it to add custom operations. Here's an example of how you can create an extension to add a pow
function to Operable
, which raises a value to a given power:
public extension Operable {
/// Raises the value to the given power
static func pow(_ value: Self, power: Int) -> Self {
var result = value
for _ in 1..<power {
result = result * value
}
return result
}
}
With this extension, you can now use the pow
function on any type that conforms to Operable
. Here's an example of how you can use it on both CGFloat
and CGPoint
:
import MathEnhancer
let floatA: CGFloat = 2.0
let floatB = CGFloat.pow(floatA, power: 3) // 8.0
let pointA = CGPoint(x: 2, y: 3)
let pointB = CGPoint.pow(pointA, power: 2) // CGPoint(x: 4, y: 9)
In the example above, pow
is used to raise a CGFloat
value to the power of 3, and a CGPoint
to the power of 2. Since both types conform to Operable
, the pow
function can be used on them.
CGPoint
ExtensionThis extension adds useful methods and operator overloads to CGPoint
. Most of these extension methods are also available for CGSize
distanceTo(_:)
Returns the distance between the receiver and the given point.
let pointA = CGPoint(x: 1, y: 1)
let pointB = CGPoint(x: 4, y: 5)
let distance = pointA.distanceTo(pointB)
// distance == 5.0
distanceXYTo(_:)
Returns the distance between the receiver and the given point in x and y components.
let pointA = CGPoint(x: 1, y: 1)
let pointB = CGPoint(x: 4, y: 5)
let distance = pointA.distanceXYTo(pointB)
// distance == CGPoint(x: 3, y: 4)
vectorLength
Returns the length between the receiver and CGPoint.zero.
let pointA = CGPoint(x: 3, y: 4)
let length = pointA.vectorLength
// length == 5.0
rounded(decimal:)
Returns a new CGPoint
that has its x and y coordinates rounded to the given number of decimal places.
let pointA = CGPoint(x: 3.14159, y: 2.71828)
let roundedPoint = pointA.rounded(decimal: 2)
// roundedPoint == CGPoint(x: 3.14, y: 2.72)
colinear(_:_:)
Returns a Boolean indicating whether the three points are collinear.
let pointA = CGPoint(x: 1, y: 1)
let pointB = CGPoint(x: 2, y: 2)
let pointC = CGPoint(x: 3, y: 3)
let collinear = pointA.colinear(pointB, pointC)
// collinear == true
rotate(around:byDegrees:)
and rotate(around:byAngle:)
angle(inCircleWithCenter:center:toPointOnCircle:)
scale(from:by:)
and scale(forReaching:byScalingFrom:)
add(x:)
, add(y:)
, subtract(x:)
, subtract(y:)
, divide(xBy:)
, divide(yBy:)
, and multiply(xBy:)
, multiply(yBy:)
Here are some examples of how these methods can be used:
let point1 = CGPoint(x: 10, y: 10)
let point2 = CGPoint(x: 20, y: 20)
// Calculate the distance between two points
let distance = point1.distanceTo(point2)
// Rotate a point around another point
let center = CGPoint(x: 15, y: 15)
let rotatedPoint = point1.rotate(around: center, byDegrees: 45)
// Scale a point to reach a target point from another point
let target = CGPoint(x: 30, y: 30)
let scaledPoint = point1.scale(forReaching: target, byScalingFrom: center)
// Add or subtract values to/from the x or y component of a point
let point3 = point1.add(x: 5).subtract(y: 2)
// Divide or multiply the x or y component of a point by a value
let point4 = point1.multiply(xBy: 2).divide(yBy: 3)
// Convert a point to a size
let size = CGPoint(x: 100, y: 200).sizeValue
area
: Returns the total area of the rectangle.let rect = CGRect(x: 0, y: 0, width: 10, height: 20)
let area = rect.area // area = 200
center
: Returns the center point of the rectangle.var rect = CGRect(x: 0, y: 0, width: 10, height: 20)
let center = rect.center // center = CGPoint(x: 5, y: 10)
// You can also set the center point of the rectangle:
rect.center = CGPoint(x: 20, y: 30)
topLeft
, bottomLeft
, topRight
, bottomRight
: Returns the specified point of the rectangle.let rect = CGRect(x: 0, y: 0, width: 10, height: 20)
let topLeft = rect.topLeft // topLeft = CGPoint(x: 0, y: 0)
let bottomLeft = rect.bottomLeft // bottomLeft = CGPoint(x: 0, y: 20)
let topRight = rect.topRight // topRight = CGPoint(x: 10, y: 0)
let bottomRight = rect.bottomRight // bottomRight = CGPoint(x: 10, y: 20)
// You can also set the specified point of the rectangle:
rect.topLeft = CGPoint(x: 5, y: 5)
A set of methods to make initalization of CoreGraphic types easier
init(center:size:)
: Initializes a new CGRect
with a center point and size.let center = CGPoint(x: 50, y: 50)
let size = CGSize(width: 100, height: 200)
let rect = CGRect(center: center, size: size) // rect = CGRect(x: 0, y: 0, width: 100, height: 200)
init(_ size: CGSize)
, init(xy: CGFloat)
: Initializes a new CGPoint
with the specified parameters.let size = CGSize(width: 100, height: 200)
let point = CGPoint(size) // point = CGPoint(x: 100, y: 200)
let xy = CGFloat(50)
let point2 = CGPoint(xy: xy) // point2 = CGPoint(x: 50, y: 50)
init(_ point: CGPoint)
, init(wh: CGFloat)
: Initializes a new CGSize
with the specified parameters.let point = CGPoint(x: 100, y: 200)
let size = CGSize(point) // size = CGSize(width: 100, height: 200)
let wh = CGFloat(50)
let size2 = CGSize(wh: wh) // size2 = CGSize(width: 50, height: 50)
MathEnhancer was developed by Ilias Nikolaidis Olsson.
If you'd like to contribute to MathEnhancer, feel free to submit a pull request or open an issue. Your contributions are always welcome!
MathEnhancer is released under the MIT license. See LICENSE for details.
link |
Stars: 0 |
Last commit: 1 week ago |
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics