Skip to content

Instantly share code, notes, and snippets.

@damuellen
Created May 13, 2016 09:51
Show Gist options
  • Save damuellen/4e14d45506831191b7f2eaa113dbd7af to your computer and use it in GitHub Desktop.
Save damuellen/4e14d45506831191b7f2eaa113dbd7af to your computer and use it in GitHub Desktop.
Largest-Triangle-Three Bucket Downsampling
func downsample(values: [(x:Double, y: Double)], threshold: Int) -> [(x:Double,y: Double)] {
guard values.count > threshold && values.count > 2 else { return values }
let bucketSize = (values.count - 2) / (threshold - 2)
var A = 0, nextA = 0
var out = [(x:Double, y: Double)]()
var maxAreaPoint: (x:Double, y: Double) = (x:0, y: 0)
out.append(values.first!)
for i in 0..<(threshold - 2) {
var avgRangeStart = (i + 1) * bucketSize + 1
var avgRangeEnd = (i + 2) * bucketSize + 1
avgRangeEnd = avgRangeEnd < values.count ? avgRangeEnd : values.count
let avgRangeLength = avgRangeEnd - avgRangeStart
var avgX = 0.0, avgY = 0.0
while avgRangeStart < avgRangeEnd {
avgX += values[avgRangeStart].x
avgY += values[avgRangeStart].y
avgRangeStart += 1;
}
avgX /= Double(avgRangeLength)
avgY /= Double(avgRangeLength)
var rangeOffs = (i + 0) * bucketSize + 1
let rangeTo = (i + 1) * bucketSize + 1
let pointAx = values[A].x
let pointAy = values[A].y
var maxArea = -1.0;
while rangeOffs < rangeTo {
let x = (pointAx - avgX) * ( values[rangeOffs].y - pointAy)
let y = (pointAx - values[rangeOffs].x ) * (avgY - pointAy)
let area = abs ( x - y ) * 0.5;
if area > maxArea {
maxArea = area;
maxAreaPoint = values[rangeOffs]
nextA = rangeOffs
}
rangeOffs += 1
}
out.append( maxAreaPoint )
A = nextA
}
out.append (values.last!)
return out
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment