2016-05-23 1 views
2

Я отслеживаю местоположение пользователей в своем приложении в базе данных со всеми координатами. Затем я делаю некоторые вещи для выбора диапазона координат за временные рамки, но при сохранении его на сервере требуется много времени из-за большого объема данных. (15 минут - 900 CLCoordinate2D, и это совсем немного).Уменьшить массив координат

Что я хочу сделать, так это удалить координату, пересекаемую предыдущей и следующей координатами. Использование слишком простых координат для иллюстративных целей, но представьте, что это делается на реальных координатах в массиве из нескольких тысяч объектов.

Пример:

0,0 //Keep 
1,1 //Drop 
2,2 //Drop 
3,3 //Keep 
3,4 //Keep 
4,4 //Keep 
5,3 //Keep 

Или хреново визуализируется: enter image description here

Я знаю, что, вероятно, следует использовать некоторый вектор материал, но я не очень хорошо в математике. Как уменьшить этот массив, чтобы удалить устаревшие точки?

+0

Они равномерно распределены во времени? – Grimxn

+0

Менеджер местоположения с BestForNavigation дает обновление примерно каждые 1 секунду. –

ответ

2

Вы могли бы попробовать что-то вроде этого ...

var coordTimes:[(coord: CLLocationCoordinate2D, time: Double)] = [] 
// ... 
func appendCoord(newCoord: CLLocationCoordinate2D, newTime: Double) { 
    guard coordTimes.count > 1 else { 
     coordTimes.append((newCoord, newTime)) 
     return 
    } 
    let n = coordTimes.count 
    // So there are at least two already in the array 
    let c0 = coordTimes[n - 2].coord 
    let t0 = coordTimes[n - 2].time 
    let c1 = coordTimes[n - 1].coord 
    let t1 = coordTimes[n - 1].time 
    let dt = t1 - t0 
    let dtNew = newTime - t0 

    guard (dtNew > 0) && (dt > 0) else { 
     // decide what to do if zero time intervals. Shouldn't happen 
     return 
    } 
    // Scale the deltas by the time interval... 
    let dLat = (c1.latitude - c0.latitude)/dt 
    let dLon = (c1.longitude - c0.longitude)/dt 
    let dLatNew = (newCoord.latitude - c0.latitude)/dtNew 
    let dLonNew = (newCoord.longitude - c0.longitude)/dtNew 

    let tolerance = 0.00001 // arbitrary - choose your own 
    if (abs(dLat - dLatNew) <= tolerance) && (abs(dLon - dLonNew) <= tolerance) { 
     // Can be interpolated - replace the last one 
     coordTimes[n - 1] = (newCoord, newTime) 
    } else { 
     // Can't be interpolated, append new point 
     coordTimes.append((newCoord, newTime)) 
    } 
} 

Толерантность имеет важное значение, поскольку вы вряд ли получите точно соответствующие интервалы. Кроме того, для геодезистов среди вас нет необходимости преобразовывать в координаты карты или вычислять истинные расстояния, поскольку ОП просто хочет знать, могут ли координаты быть интерполированы.

+0

Это выглядит многообещающим, проверит его сразу. Однако я не вижу актуальности времени. Возможно, я должен был быть более наглядным, но местоположения уже сохранены и отсортированы от самых старых до новейших, а не добавлены «на лету». –

+0

Если это так, просто замените время исходным номером индекса (а не номером сжатого индекса) – Grimxn