ios-curve-interpolation icon indicating copy to clipboard operation
ios-curve-interpolation copied to clipboard

Swift integration

Open jrmgx opened this issue 9 years ago • 2 comments

I had a hard time to integrate your lib into my swift project, (problems with extension translated to unrecongnised convenience init)

So after a while i decided to translate the interpolateCGPointsWithHermite in native swift 2+ I won't do a pull request as it is not appropriated (my opinion) but I can share that here

I made an extension out of it (as a static helper) it could have been a convenience init or a fully static helper (the choice is your)

extension UIBezierPath {

    static func interpolateHermiteFor(points: [CGPoint], closed: Bool = false) -> UIBezierPath {
        guard points.count >= 2 else {
            return UIBezierPath()
        }

        if points.count == 2 {
            let bezierPath = UIBezierPath()
            bezierPath.moveToPoint(points[0])
            bezierPath.addLineToPoint(points[1])
            return bezierPath
        }

        let nCurves = closed ? points.count : points.count - 1

        let path = UIBezierPath()
        for i in 0..<nCurves {
            var curPt = points[i]
            var prevPt: CGPoint, nextPt: CGPoint, endPt: CGPoint
            if i == 0 {
                path.moveToPoint(curPt)
            }

            var nexti = (i+1)%points.count
            var previ = (i-1 < 0 ? points.count-1 : i-1)

            prevPt = points[previ]
            nextPt = points[nexti]
            endPt = nextPt

            var mx: CGFloat
            var my: CGFloat
            if closed || i > 0 {
                mx  = (nextPt.x - curPt.x) * CGFloat(0.5)
                mx += (curPt.x - prevPt.x) * CGFloat(0.5)
                my  = (nextPt.y - curPt.y) * CGFloat(0.5)
                my += (curPt.y - prevPt.y) * CGFloat(0.5)
            }
            else {
                mx = (nextPt.x - curPt.x) * CGFloat(0.5)
                my = (nextPt.y - curPt.y) * CGFloat(0.5)
            }

            var ctrlPt1 = CGPointZero
            ctrlPt1.x = curPt.x + mx / CGFloat(3.0)
            ctrlPt1.y = curPt.y + my / CGFloat(3.0)

            curPt = points[nexti]

            nexti = (nexti + 1) % points.count
            previ = i;

            prevPt = points[previ]
            nextPt = points[nexti]

            if closed || i < nCurves-1 {
                mx  = (nextPt.x - curPt.x) * CGFloat(0.5)
                mx += (curPt.x - prevPt.x) * CGFloat(0.5)
                my  = (nextPt.y - curPt.y) * CGFloat(0.5)
                my += (curPt.y - prevPt.y) * CGFloat(0.5)
            }
            else {
                mx = (curPt.x - prevPt.x) * CGFloat(0.5)
                my = (curPt.y - prevPt.y) * CGFloat(0.5)
            }

            var ctrlPt2 = CGPointZero
            ctrlPt2.x = curPt.x - mx / CGFloat(3.0)
            ctrlPt2.y = curPt.y - my / CGFloat(3.0)

            path.addCurveToPoint(endPt, controlPoint1:ctrlPt1, controlPoint2:ctrlPt2)
        }

        if closed {
            path.closePath()
        }

        return path
    }
}

nb: it takes an array of CGPoint as you can do that in swift

jrmgx avatar Dec 01 '15 14:12 jrmgx

Thank you so much! I originally got my swift code to work with the objective-c class, but this helped simplify it.

hunterbryant avatar Jan 05 '16 18:01 hunterbryant

BTW, I did my own Swift ports of these, found here on Stack Overflow.

robertmryan avatar Jan 11 '16 19:01 robertmryan