Metron is a comprehensive collection of geometric functions and types that extend the 2D geometric primitives

Overview

Build Status GitHub Release CocoaPods Release Carthage Compatible SwiftPM Compatible Supported Platforms

Metron

Geometry, simplified.

Metron is a comprehensive collection of geometric functions and types that extend the 2D geometric primitives provided by CoreGraphics. Completely written in Swift, Metron allows you to express complex geometric calculations in very intuitive statements:

Example 1.

Circle(in: viewFrame).contains(touchPoint)

↳ creates a Circle that fits (centered) inside viewFrame, and checks if the touchPoint is inside that circle.

Example 2.

(Angle(.pi) + Angle(270, unit: .degrees)).normalized // Angle of 0.5pi (90°)

↳ adds two Angles, one expressed in radians (default) and one in degrees. The sum is normalized to within 0 and 2𝛑 radians (or 0 and 360 degrees).

Example 3.

LineSegment(a: startPoint, b: currentPoint).intersection(with: viewFrame.lineSegment(for: minYEdge))

↳ creates a LineSegment between a (touch) start point and current point, and returns the intersection with the minYEdge of a view's frame (if these line segments indeed intersect).

Example 4.

let rotatedPoints = viewFrame.points.map { $0.applying(rotationTransform, anchorPoint: rotationPoint) }
let path: CGPath = Polygon(points: rotatedPoints).path

↳ maps each corner point of a view's frame (a CGRect) to a point to which a rotationTransform is applied, taking rotationPoint as the anchor point for the transform. With these points, a Polygon is initialized, representing the rotated rectangular frame of the view. From that polygon, we derive a CGPath that can then be drawn.

And there's much more...

Extensions

For CGPoint

  • Distance to other CGPoint
  • Clipping to CGRect
  • Relative position in CGRect
  • Normalized position in CGRect
  • Convert to CGVector
  • Round to non-decimal components
  • Addition, subtraction, multiplication...
  • Convex hull for an array of CGPoints (returns a Polygon)

For CGVector

  • Magnitude
  • Angle
  • Convenience initializer with magnitude and angle
  • Convert to CGPoint
  • Inverse
  • Dominant edge
  • Dominant corner
  • Derive line through point
  • Derive line segment from point
  • CGAffineTransform extensions
  • Addition, subtraction, multiplication...

For CGSize

  • Area
  • Swap width and height
  • Clip to other CGSize
  • Scaling using multiplication and division

For CGRect

  • Many convenience initializers, including AspectFit / AspectFill for size
  • Scaling
  • Corner points
  • Edges as line segments
  • Area
  • Center
  • Perimeter
  • CGPath

For CGRectEdge

  • Axis (x or y)
  • Adjacent corners
  • Opposite edge

For CGAffineTransform

  • Create translation transform using CGVector
  • Apply transform with a specified anchor point

New Types

Line

  • Slope
  • Y-intercept
  • X-intercept
  • Horizontal? / vertical? / parallel(to: ...)?
  • Get a perpendicular line
  • Determine intersection with other Line or LineSegment

LineSegment

  • Length
  • Derive a Line
  • Rotate
  • Determine intersection with other Line or LineSegment
  • CGPath

Circle

  • Radius
  • Diameter
  • Circumference
  • Area
  • Center
  • Width / Height
  • Bounding rect
  • Contains point?
  • CGPath
  • Points along the perimeter (divide the circle into steps, rotating in a specific direction...)

Triangle

  • Vertices (as CGPoint)
  • Sides (as LineSegment)
  • Angles (as Angle, see further on)
  • Angle bisectors (as LineSegment)
  • Altitudes (as LineSegment)
  • Equilateral? / isosceles? / scalene? / right? / oblique? / acute? / obtuse?
  • Centroid
  • Circumcenter
  • Incenter
  • Orthocenter
  • Area
  • Bounding rect
  • Contains point?
  • CGPath

Square

  • Edge length
  • Area
  • Perimeter
  • Center
  • CGPath
  • CGRect

Polygon

  • Init with points or with line segments
  • Edge count
  • Self-intersecting?
  • Convex? / concave?
  • Area
  • Perimeter
  • Center
  • Bounding rect
  • Contains point?
  • CGPath

Corner

  • Adjacent edges (CGRectEdges)
  • Opposite corner

Angle

  • Init with radians or degrees
  • Convert unit
  • Normalize
  • Invert
  • Compare
  • Addition, subtraction, multiplication...
  • Basic trigonometric functions also accept Angle
  • Create rotation CGAffineTransform with Angle

Installation

CocoaPods

Metron is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "Metron"

Carthage

Metron is also available through Carthage. To install it, simply add the following line to your Cartfile:

github "toineheuvelmans/Metron"

Swift Package Manager

Metron can also be used with the Swift Package Manager. Add Metron to the dependencies value of your Package.swift:

dependencies: [
    .Package(url: "https://github.com/toineheuvelmans/metron.git", majorVersion: 1)
]

Suggestions or feedback?

Feel free to create a pull request, open an issue or find me on Twitter.

License

Metron is available under the MIT license. See the LICENSE file for more info.

Comments
  • Podspec is on 1.0.3 while release is on 1.0.4

    Podspec is on 1.0.3 while release is on 1.0.4

    Hi, thanks for all your work!.

    I noticed the tagged release is on 1.0.4 but the spec file is on 1.0.3. I import this project via github and grabs that version. Another issue is that on cocoapods the version available is 1.0.2 which doesn't build on swift 5, maybe also update that?

    opened by RubenAstudillo 3
  • Latest release won't build in Carthage with Xcode 10.2

    Latest release won't build in Carthage with Xcode 10.2

    The latest release won't build in Carthage with Xcode 10.2 due to Swift 3.0 being deprecated.

    The master branch is compatible, but a new release hasn't been created yet. @toineheuvelmans would it be possible to create a new release including the new changes on master?

    opened by rzulkoski 2
  • Trouble getting Example playground to run.

    Trouble getting Example playground to run.

    Hi! Great library!

    I'm getting this error when attempting to run the example playground:

    error: /var/folders/y0/p7w_bnh91nv7vsl4kcymcxbh0000gq/T/playground6-adf4ec..swift:3:8: error: no such module 'Metron_Sources'
    import Metron_Sources
    

    Any ideas?

    BTW, suggest adding a note about running pod install. From the Playground:

    NOTE: Run pod install in the Example folder and then open the Xcode workspace. You will need to build the project first before Metron is available in these playgrounds. Ensure that you have a Simulator-type device selected when building.

    opened by davidbjames 2
  • Fix line contains point method

    Fix line contains point method

    Fixes #15. When a line is defined as vertical line, the contains method returned false, even though the given point is contained within the line. The fix for this issue considers both definition types and checks whether the x-position matches with the x-coordinate of the given point. If this is the case it is guranteed that the given point is contained in the line.

    opened by LinkAndreas 1
  • LineSegment intersection(with:) doesn't work

    LineSegment intersection(with:) doesn't work

    Hi, It seems like there is an issue with the calcul used in intersection(with:) function. If you try this small example, you won't find any intersect point whereas it actually exist

    let lineA = LineSegment(a: CGPoint(x:187.5, y:108.873626373626), b: CGPoint(x:352.335164835165, y:108.873626373626))
    let lineB = LineSegment(a: CGPoint(x:272.0, y:88.0), b: CGPoint(x:354.0, y:388.0))
    let point = lineA.intersection(with: lineB) //return nil
    

    geogebra-export

    opened by florentdouine 1
  • Build error

    Build error

    I get the following error when trying to build my project after adding Metron via Podfile.

    Polygon.swift
    Error:(233, 34) contextual closure type '(CGPoint, CGPoint) -> Bool' expects 2 arguments, but 1 was used in closure body
    

    I'm using the following swift compiler: Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2) Target: x86_64-apple-macosx10.9

    opened by erf 1
  • Build error using XCode9 / Swift 4 in Polygon, sorted

    Build error using XCode9 / Swift 4 in Polygon, sorted

    Build error using XCode9 / Swift 4. Polygon, sorted requires two arguments.

    Link: https://github.com/toineheuvelmans/Metron/blob/712905ebd8efe7340f86bb74694de637cccd85fa/Metron/Classes/Polygon.swift#L233

    opened by erf 1
  • LineSegment.intersection(with:) not working properly

    LineSegment.intersection(with:) not working properly

    Confirming that LineSegment.intersection(with:) may return nil for valid intersection cases:

    let s1 = LineSegment(a: .init(x: 187.50440979003906, y: 543.5147094726562), b: .init(x: 333.1461486816406, y: -109.8446273803711))
    let s2 = LineSegment(a: .init(x: 0, y: 0), b: .init(x: 375, y: 0))
    let intersection = s1.intersection(with: s2) // nil
    

    Should not be nil, as the two segments are intersecting at a point:

    Screen Shot 2020-10-06 at 10 22 03 PM
    opened by nazariyg 1
  • Polygon contains point, returning incorrect result

    Polygon contains point, returning incorrect result

    My polygon CGPoints:

    (0.0, 0.0), (0, 4.6849846839904785), (-3.7979183197021484, 8.482921600341797), (-8.482903480529785, 8.482928276062012), (-13.167887687683105, 8.48293399810791), (-16.965824127197266, 4.685009002685547), (-16.965829849243164, 0), (-16.965837478637695, -4.684959888458252), (-13.167911529541016, -8.48289680480957), (-8.482927322387695, -8.482903480529785), (-3.7979419231414795, -8.482909202575684), (0, -4.6849846839904785), (0.0, 0.0)
    

    My point:

    (-14.683422088623047, 1.410199522972107)
    

    Result:

    polygon.contains(point) // false
    

    It does contain the point

    opened by ProjectDent 0
  • LineSegment intersection returning nil incorrectly

    LineSegment intersection returning nil incorrectly

    let lineSegment1 = Metron.LineSegment(a: CGPoint(x: 5.203594207763672, y: 3.6903457641601562), b: CGPoint(x: -9.671459197998047, y: 9.507403373718262))
    let lineSegment2 = Metron.LineSegment(a: CGPoint(x: (3.9301047325134277), y: 3.930098295211792), b: CGPoint(x: 3.930110216140747, y: 8.778124809265137))
    	
    let intersection = lineSegment1.intersection(with: lineSegment2)
    

    Intersection returns nil, when it should return as CGPoint(x: 3.9301050246323883, y: 4.18835808998847)

    You can see these numbers on Desmos: https://www.desmos.com/calculator/aqc2syqz2s

    I have another function in my project which does the same job, which may be able to give a hint as to why the Metron function isn't working properly:

    extension CGPoint {
        static func intersectionOfLines(line1: (a: CGPoint, b: CGPoint), line2: (a: CGPoint, b: CGPoint)) -> CGPoint? {
    	
            let distance = (line1.b.x - line1.a.x) * (line2.b.y - line2.a.y) - (line1.b.y - line1.a.y) * (line2.b.x - line2.a.x)
            if distance == 0 {
                print("intersection issue, parallel lines")
                    return nil
            }
    	
    	let u = ((line2.a.x - line1.a.x) * (line2.b.y - line2.a.y) - (line2.a.y - line1.a.y) * (line2.b.x - line2.a.x)) / distance
    	let v = ((line2.a.x - line1.a.x) * (line1.b.y - line1.a.y) - (line2.a.y - line1.a.y) * (line1.b.x - line1.a.x)) / distance
    	
    	if (u < 0.0 || u > 1.0) {
    		print("intersection issue, intersection not inside line1")
    		return nil
    	}
    	if (v < 0.0 || v > 1.0) {
    		print("intersection issue, intersection not inside line2")
    		return nil
    	}
    	
    	return CGPoint(
    		x: line1.a.x + u * (line1.b.x - line1.a.x),
    		y: line1.a.y + u * (line1.b.y - line1.a.y))
            }
    }
    
    opened by ProjectDent 0
  • Request for adding (bezier) curves

    Request for adding (bezier) curves

    If you should choose to pursue implementing a Bezier cubic curve, my repository CeranPaul/SketchCurves has class "Cubic" that could be helpful to you.

    I haven't spent any time on a quadratic curve, but can see the usefulness of that for importing and exporting SVG's.

    My repository needs to have its Ellipse class fleshed out. I'll be in touch when I have something useful.

     Paul
    
    feature request 
    opened by CeranPaul 1
  • Support for ellipses

    Support for ellipses

    Metron is a lovely little library and has saved me a ton of time! Circle works for some cases, but not for ellipses. Seeing this officially supported would be great.

    feature request 
    opened by matt-curtis 3
Releases(1.0.4)
Owner
Toine Heuvelmans
Lead Mobile Engineer @ Touchwonders. Also experience with digital signal processing, beer brewing and parenting.
Toine Heuvelmans
VectorMath is a Swift library for Mac and iOS that implements common 2D and 3D vector and matrix functions

Purpose VectorMath is a Swift library for Mac and iOS that implements common 2D and 3D vector and matrix functions, useful for games or vector-based g

Nick Lockwood 341 Dec 31, 2022
SwiftMath is a Swift framework providing some useful math constructs and functions

SwiftMath is a Swift framework providing some useful math constructs and functions, like complex numbers, vectors, matrices, quaternions, and polynomials.

Matteo Battaglio 175 Dec 2, 2022
A set of protocols for Arithmetic, Statistics and Logical operations

Arithmosophi - Arithmosoϕ Arithmosophi is a set of missing protocols that simplify arithmetic and statistics on generic objects or functions. As Equat

Eric Marchand 66 Jul 9, 2022
Overload +-*/ operator for Swift, make it easier to use (and not so strict)

Easy-Cal-Swift Overview This file is an overloading of +-*/ operator for Swift, to make it easier to use (and not so strict) It can make your life wit

Wei Wang 272 Jun 29, 2022
Numpy-like library in swift. (Multi-dimensional Array, ndarray, matrix and vector library)

Matft Matft is Numpy-like library in Swift. Function name and usage is similar to Numpy. Matft Feature & Usage Declaration MfArray MfType Subscription

null 80 Dec 21, 2022
Beautiful math equation rendering on iOS and MacOS

iosMath iosMath is a library for displaying beautifully rendered math equations in iOS and MacOS applications. It typesets formulae written using the

Kostub Deshmukh 1.3k Dec 21, 2022
A complete set of primitives for concurrency and reactive programming on Swift

A complete set of primitives for concurrency and reactive programming on Swift 1.4.0 is the latest and greatest, but only for Swift 4.2 and 5.0 use 1.

AsyncNinja 156 Aug 31, 2022
Several synchronization primitives and task synchronization mechanisms introduced to aid in modern swift concurrency.

AsyncObjects Several synchronization primitives and task synchronization mechanisms introduced to aid in modern swift concurrency. Overview While Swif

SwiftyLab 20 Jan 3, 2023
Functional Concurrency Primitives

Concurrent Concurrent is a collection of functional concurrency primitives inspired by Concurrent ML and Concurrent Haskell. Traditional approaches to

TypeLift 206 Dec 24, 2022
A stable, mature and comprehensive Objective-C library for Twitter REST API 1.1

STTwitter A stable, mature and comprehensive Objective-C library for Twitter REST API 1.1 Like a FOSS version of Twitter Fabric TwitterKit, without th

Nicolas Seriot 1k Nov 30, 2022
A comprehensive SDK for scanning Digimarc digital watermarks and the most common retail 1D barcodes & QR codes.

##Digimarc Mobile SDK for Apple Platforms The Digimarc Mobile SDK (DM SDK) is a comprehensive and robust scanning software for Digimarc Barcode (Produ

Digimarc 5 Jun 1, 2022
📱 A comprehensive test task for creating an autolayout interface, requesting an API and JSON parsing from Effective Mobile.

ECOMMERCE A comprehensive test task for creating an autolayout interface, requesting an API and JSON parsing from Effective Mobile. ??‍?? Design ✨ Fea

Daniel Tvorun 4 Nov 21, 2022
Functional data types and functions for any project

Swiftx Swiftx is a Swift library containing functional abstractions and extensions to the Swift Standard Library. Swiftx is a smaller and simpler way

TypeLift 219 Aug 30, 2022
Functional data types and functions for any project

Swiftx Swiftx is a Swift library containing functional abstractions and extensions to the Swift Standard Library. Swiftx is a smaller and simpler way

TypeLift 219 Aug 30, 2022
A comprehensive, lightweight string extension for Swift

SwiftString SwiftString is a lightweight string extension for Swift. This library was motivated by having to search StackOverflow for common string op

Andrew Mayne 1.6k Dec 30, 2022
🚀Comprehensive Redux library for SwiftUI, ensures State consistency across Stores with type-safe pub/sub pattern.

??Comprehensive Redux library for SwiftUI, ensures State consistency across Stores with type-safe pub/sub pattern.

Cheng Zhang 18 Mar 9, 2022
A fast, convenient and nonintrusive conversion framework between JSON and model. Your model class doesn't need to extend any base class. You don't need to modify any model file.

MJExtension A fast, convenient and nonintrusive conversion framework between JSON and model. 转换速度快、使用简单方便的字典转模型框架 ?? ✍??Release Notes: more details Co

M了个J 8.5k Jan 3, 2023
Argo is a library that lets you extract models from JSON or similar structures in a way that's concise, type-safe, and easy to extend

Argo is a library that lets you extract models from JSON or similar structures in a way that's concise, type-safe, and easy to extend. Using Argo

thoughtbot, inc. 3.5k Dec 20, 2022
A video composition framework build on top of AVFoundation. It's simple to use and easy to extend.

A high-level video composition framework build on top of AVFoundation. It's simple to use and easy to extend. Use it and make life easier if you are implementing video composition feature.

VideoFlint 1.4k Dec 25, 2022
A Cocoa library to extend the Objective-C programming language.

The Extended Objective-C library extends the dynamism of the Objective-C programming language to support additional patterns present in other programm

Justin Spahr-Summers 4.5k Dec 30, 2022