├── CGPoint+Utilities.swift ├── CatmullRom.swift ├── LICENSE └── README.md /CGPoint+Utilities.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension CGPoint{ 4 | func translate(x: CGFloat, _ y: CGFloat) -> CGPoint { 5 | return CGPointMake(self.x + x, self.y + y) 6 | } 7 | 8 | func translateX(x: CGFloat) -> CGPoint { 9 | return CGPointMake(self.x + x, self.y) 10 | } 11 | 12 | func translateY(y: CGFloat) -> CGPoint { 13 | return CGPointMake(self.x, self.y + y) 14 | } 15 | 16 | func invertY() -> CGPoint { 17 | return CGPointMake(self.x, -self.y) 18 | } 19 | 20 | func xAxis() -> CGPoint { 21 | return CGPointMake(0, self.y) 22 | } 23 | 24 | func yAxis() -> CGPoint { 25 | return CGPointMake(self.x, 0) 26 | } 27 | 28 | func addTo(a: CGPoint) -> CGPoint { 29 | return CGPointMake(self.x + a.x, self.y + a.y) 30 | } 31 | 32 | func deltaTo(a: CGPoint) -> CGPoint { 33 | return CGPointMake(self.x - a.x, self.y - a.y) 34 | } 35 | 36 | func multiplyBy(value:CGFloat) -> CGPoint{ 37 | return CGPointMake(self.x * value, self.y * value) 38 | } 39 | 40 | func length() -> CGFloat { 41 | return CGFloat(sqrt(CDouble( 42 | self.x*self.x + self.y*self.y 43 | ))) 44 | } 45 | 46 | func normalize() -> CGPoint { 47 | let l = self.length() 48 | return CGPointMake(self.x / l, self.y / l) 49 | } 50 | 51 | static func fromString(string: String) -> CGPoint { 52 | var s = string.stringByReplacingOccurrencesOfString("{", withString: "") 53 | s = s.stringByReplacingOccurrencesOfString("}", withString: "") 54 | s = s.stringByReplacingOccurrencesOfString(" ", withString: "") 55 | 56 | let x = NSString(string: s.componentsSeparatedByString(",").first! as String).doubleValue 57 | let y = NSString(string: s.componentsSeparatedByString(",").last! as String).doubleValue 58 | 59 | return CGPointMake(CGFloat(x), CGFloat(y)) 60 | } 61 | } -------------------------------------------------------------------------------- /CatmullRom.swift: -------------------------------------------------------------------------------- 1 | 2 | #if !TARGET_OS_IPHONE 3 | import Cocoa 4 | typealias UIBezierPath = NSBezierPath 5 | #endif 6 | 7 | extension UIBezierPath { 8 | 9 | convenience init?(catmullRomPoints: [CGPoint], closed: Bool, alpha: CGFloat) { 10 | self.init() 11 | 12 | if catmullRomPoints.count < 4 { 13 | return nil 14 | } 15 | 16 | let startIndex = closed ? 0 : 1 17 | let endIndex = closed ? catmullRomPoints.count : catmullRomPoints.count - 2 18 | 19 | for var i = startIndex; i < endIndex; ++i { 20 | let p0 = catmullRomPoints[i-1 < 0 ? catmullRomPoints.count - 1 : i - 1] 21 | let p1 = catmullRomPoints[i] 22 | let p2 = catmullRomPoints[(i+1)%catmullRomPoints.count] 23 | let p3 = catmullRomPoints[(i+1)%catmullRomPoints.count + 1] 24 | 25 | let d1 = p1.deltaTo(p0).length() 26 | let d2 = p2.deltaTo(p1).length() 27 | let d3 = p3.deltaTo(p2).length() 28 | 29 | var b1 = p2.multiplyBy(pow(d1, 2 * alpha)) 30 | b1 = b1.deltaTo(p0.multiplyBy(pow(d2, 2 * alpha))) 31 | b1 = b1.addTo(p1.multiplyBy(2 * pow(d1, 2 * alpha) + 3 * pow(d1, alpha) * pow(d2, alpha) + pow(d2, 2 * alpha))) 32 | b1 = b1.multiplyBy(1.0 / (3 * pow(d1, alpha) * (pow(d1, alpha) + pow(d2, alpha)))) 33 | 34 | var b2 = p1.multiplyBy(pow(d3, 2 * alpha)) 35 | b2 = b2.deltaTo(p3.multiplyBy(pow(d2, 2 * alpha))) 36 | b2 = b2.addTo(p2.multiplyBy(2 * pow(d3, 2 * alpha) + 3 * pow(d3, alpha) * pow(d2, alpha) + pow(d2, 2 * alpha))) 37 | b2 = b2.multiplyBy(1.0 / (3 * pow(d3, alpha) * (pow(d3, alpha) + pow(d2, alpha)))) 38 | 39 | if i == startIndex { 40 | moveToPoint(p1) 41 | } 42 | 43 | #if !TARGET_OS_IPHONE 44 | curveToPoint(p2, controlPoint1: b1, controlPoint2: b2) 45 | #else 46 | addCurveToPoint(p2, controlPoint1: b1, controlPoint2: b2) 47 | #endif 48 | } 49 | 50 | if closed { 51 | closePath() 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 André Lind 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | swift-catmullrom 2 | ================ 3 | 4 | A CatmullRom implementation in Swift 5 | --------------------------------------------------------------------------------