0

I am designing a function that will take an array of CGPoints, treat it as end points of a poly-line, and insert intermediate points using Catmull-Rom smoothing to create an approximation of a curve that passes through those points.

The function can be defined as a global function:

func smoothPoints(array: [CGPoint], granularity: Int = 4) -> [CGPoint] {
    return [CGPoint]() //Placeholder code for actual implementation
  }

But I'd like to be able to define it as a constrained extension on the Array type, so that it will only operate on arrays of CGPoints. Is that possible?

The only examples of constrained extensions I've been able to find in Swift 3 constrain the array elements to objects that conform to a protocol, not a specific data (Struct) type.

It seems like I should be able to do something like this:

extension Array where Element: CGPoint {
func smoothPoints(granularity: Int = 4) -> [CGPoint] {
  }
}

But that gives me an error "type 'Element' constrained to non-protocol type 'CGPoint'".

The declaration

 extension Array<CGPoint>

...doesn't work either.

It seems like it should be possible to define an extension to the Array class that only operates on arrays of a specific type, but I can't figure out how to do so.

Is what I'm trying to do possible in Swift 3, or am I stuck with a global function?

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • 1
    Related: [Extend array types using where clause in Swift](http://stackoverflow.com/q/31806324/2976878), [How can I make a extension for array of specific type in Swift](http://stackoverflow.com/q/31842337/2976878). Simplest solution would be to extend `Collection` instead with the constraint `Iterator.Element == CGPoint`. – Hamish Dec 31 '16 at 14:50
  • Although if your implementation relies on O(1) indexing, you should probably extend `RandomAccessCollection` instead. – Hamish Dec 31 '16 at 14:56

1 Answers1

1

You could constrain to a protocol that exposes the functionality you need and have CGPoint conform to it:

protocol Coordinates {
    var x: CGFloat { get }
    var y: CGFloat { get }
}

extension Array where Element: Coordinates {
    func smoothPoints(granularity: Int = 4) -> [Element] {
        return []  //Placeholder code for actual implementation
    }
}

extension CGPoint: Coordinates {}

let test: [CGPoint] = [CGPoint(x: 10, y: 20)]
test.smoothPoints() // returns an Array<CGPoint>
nils
  • 1,786
  • 13
  • 18