diff --git a/Sources/RectangleTools/Synthesized Conveniences/Point2D Extensions.swift b/Sources/RectangleTools/Synthesized Conveniences/Point2D Extensions.swift index e540826..5f9987f 100644 --- a/Sources/RectangleTools/Synthesized Conveniences/Point2D Extensions.swift +++ b/Sources/RectangleTools/Synthesized Conveniences/Point2D Extensions.swift @@ -24,6 +24,25 @@ public extension Point2D { +public extension Point2D + where Length: BinaryFloatingPoint +{ + /// Creates a new point with the given values from a different type + /// + /// - Parameters: + /// - x: The X coordinate to convert + /// - y: The Y coordinate to convert + @inline(__always) + init(x: OtherLength, y: OtherLength) + where OtherLength: BinaryFloatingPoint + { + self.init(measurementX: x, + measurementY: y) + } +} + + + public extension Point2D where Length: MultiplicativeArithmetic, Length: AdditiveArithmetic, diff --git a/Sources/RectangleTools/Synthesized Conveniences/Size2D Extensions.swift b/Sources/RectangleTools/Synthesized Conveniences/Size2D Extensions.swift index 596e016..fa6f2ad 100644 --- a/Sources/RectangleTools/Synthesized Conveniences/Size2D Extensions.swift +++ b/Sources/RectangleTools/Synthesized Conveniences/Size2D Extensions.swift @@ -23,6 +23,25 @@ public extension Size2D { +public extension Point2D + where Length: BinaryFloatingPoint +{ + /// Creates a new size with the given values from a different type + /// + /// - Parameters: + /// - width: The width measurement to convert + /// - height: The height measurement to convert + @inline(__always) + init(width: OtherLength, height: OtherLength) + where OtherLength: BinaryFloatingPoint + { + self.init(measurementX: width, + measurementY: height) + } +} + + + // MARK: - CartesianMeasurable public extension Size2D @@ -50,7 +69,7 @@ public extension Size2D var maxY: Length { max(.zero, height) } - // MARK: Points + // MARK: Generic Point extremities /// The point with the smallest X and Y values in this size @inlinable @@ -67,7 +86,30 @@ public extension Size2D /// The point with the largest X and Y values in this size @inlinable func maxXmaxY() -> Point where Point.Length == Self.Length { Point.init(x: maxX, y: maxY) } +} + + + +public extension Size2D +where Length: BinaryFloatingPoint +{ + // MARK: CGPoint extremities + /// The point with the smallest X and Y values in this size + @inlinable + func minXminY() -> CGPoint { .init(measurementX: minX, measurementY: minY) } + + /// The point with the smallest X and largest Y values in this size + @inlinable + func minXmaxY() -> CGPoint { .init(measurementX: minX, measurementY: maxY) } + + /// The point with the largest X and smallest Y values in this size + @inlinable + func maxXminY() -> CGPoint { .init(measurementX: maxX, measurementY: minY) } + + /// The point with the largest X and Y values in this size + @inlinable + func maxXmaxY() -> CGPoint { .init(measurementX: maxX, measurementY: maxY) } } diff --git a/Sources/RectangleTools/Synthesized Conveniences/TwoDimensional Extensions.swift b/Sources/RectangleTools/Synthesized Conveniences/TwoDimensional Extensions.swift index 570d73d..917178a 100644 --- a/Sources/RectangleTools/Synthesized Conveniences/TwoDimensional Extensions.swift +++ b/Sources/RectangleTools/Synthesized Conveniences/TwoDimensional Extensions.swift @@ -14,6 +14,18 @@ import MultiplicativeArithmetic public extension TwoDimensional where Length: BinaryFloatingPoint { + /// Creates a new 2D with the given values from a different type + /// + /// - Parameters: + /// - measurementX: The X measurement to convert + /// - measurementY: The Y measurement to convert + init(measurementX: OtherLength, measurementY: OtherLength) + where OtherLength: BinaryFloatingPoint + { + self.init(measurementX: .init(measurementX), + measurementY: .init(measurementY)) + } + /// Creates a new 2D object by converting the values of the given one /// /// - Parameter other: Another 2D object to convert diff --git a/Tests/RectangleToolsTests/Point Tests.swift b/Tests/RectangleToolsTests/Point Tests.swift index dc98532..778005d 100644 --- a/Tests/RectangleToolsTests/Point Tests.swift +++ b/Tests/RectangleToolsTests/Point Tests.swift @@ -12,12 +12,57 @@ import RectangleTools final class Point_Tests: XCTestCase { - func testDistance() { + func testPointToPointDistance() { XCTAssertEqual(CGPoint(x: 0, y: 0).distance(to: CGPoint(x: 1, y: 1)), sqrt(2)) + XCTAssertEqual(CGPoint(x: 0, y: 0).distance(to: CGPoint(x: -1, y: 1)), sqrt(2)) + XCTAssertEqual(CGPoint(x: 0, y: 0).distance(to: CGPoint(x: 1, y: -1)), sqrt(2)) XCTAssertEqual(CGPoint(x: 0, y: 0).distance(to: CGPoint(x: -1, y: -1)), sqrt(2)) } + func testSizeExtremitiesDistance() { + var cgSize = CGSize(width: 1, height: 1) + XCTAssertEqual(cgSize.minXminY().distance(to: cgSize.maxXmaxY()), sqrt(2)) + + cgSize = CGSize(width: -1, height: 1) + XCTAssertEqual(cgSize.minXminY().distance(to: cgSize.maxXmaxY()), sqrt(2)) + + cgSize = CGSize(width: 1, height: -1) + XCTAssertEqual(cgSize.minXminY().distance(to: cgSize.maxXmaxY()), sqrt(2)) + + cgSize = CGSize(width: -1, height: -1) + XCTAssertEqual(cgSize.minXminY().distance(to: cgSize.maxXmaxY()), sqrt(2)) + } + + + func testRectExtremitiesDistance() { + var cgRect = CGRect(x: 0, y: 0, width: 1, height: 1) + XCTAssertEqual(cgRect.minXminY.distance(to: cgRect.maxXmaxY), sqrt(2)) + + cgRect = CGRect(x: 0, y: 0, width: -1, height: 1) + XCTAssertEqual(cgRect.minXminY.distance(to: cgRect.maxXmaxY), sqrt(2)) + + cgRect = CGRect(x: 0, y: 0, width: 1, height: -1) + XCTAssertEqual(cgRect.minXminY.distance(to: cgRect.maxXmaxY), sqrt(2)) + + cgRect = CGRect(x: 0, y: 0, width: -1, height: -1) + XCTAssertEqual(cgRect.minXminY.distance(to: cgRect.maxXmaxY), sqrt(2)) + + + cgRect = CGRect(x: .random(in: -1000 ... 1000), y: .random(in: -1000 ... 1000), width: 1, height: 1) + XCTAssertEqual(cgRect.minXminY.distance(to: cgRect.maxXmaxY), sqrt(2)) + + cgRect = CGRect(x: .random(in: -1000 ... 1000), y: .random(in: -1000 ... 1000), width: -1, height: 1) + XCTAssertEqual(cgRect.minXminY.distance(to: cgRect.maxXmaxY), sqrt(2)) + + cgRect = CGRect(x: .random(in: -1000 ... 1000), y: .random(in: -1000 ... 1000), width: 1, height: -1) + XCTAssertEqual(cgRect.minXminY.distance(to: cgRect.maxXmaxY), sqrt(2)) + + cgRect = CGRect(x: .random(in: -1000 ... 1000), y: .random(in: -1000 ... 1000), width: -1, height: -1) + XCTAssertEqual(cgRect.minXminY.distance(to: cgRect.maxXmaxY), sqrt(2)) + } + + func testMagnitude() { // https://www.wolframalpha.com/input?i=distance+from+%28-2%2C-1%29+to+%285%2C6%29 XCTAssertEqual(CIVector(x: -2, y: -1, z: 5, w: 6).magnitude, 7 * sqrt(2))