2016-05-23 18 views
2

Ich verfolge den Standort des Benutzers in meiner App in einer Datenbank mit allen Koordinaten. Ich mache dann ein paar Sachen, um einen Bereich von Koordinaten in einem Zeitrahmen auszuwählen, aber wenn ich es auf dem Server speichere, dauert es aufgrund der großen Datenmenge sehr lange. (15 Minuten ist 900 CLCoordinate2D 's und das ist ziemlich viel).Koordinaten-Array verkleinern

Was ich tun möchte, ist die Koordinaten zu entfernen, die von der vorhergehenden und folgenden Koordinaten geschnitten werden. Verwenden Sie für Veranschaulichungszwecke übermäßig einfache Koordinaten, aber stellen Sie sich vor, dass dies an realen Koordinaten in einem Array von ein paar tausend Objekten geschieht.

Beispiel:

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

Oder shitty sichtbar gemacht: enter image description here

Ich weiß, dass ich wahrscheinlich einige Vektor Material verwenden sollte, aber ich bin nicht in Mathe gut. Wie kann ich dieses Array reduzieren, um die veralteten Punkte zu entfernen?

+0

Sind sie zeitlich gleichmäßig verteilt? – Grimxn

+0

Location Manager mit BestForNavigation gibt ungefähr alle 1 Sekunden ein Update. –

Antwort

2

Sie so etwas wie dies versuchen könnte ...

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)) 
    } 
} 

Die Toleranz ist wichtig, da Sie sehr unwahrscheinlich sind genau passenden Abständen zu bekommen. Auch für die Geodäten unter Ihnen besteht keine Notwendigkeit, in Kartenkoordinaten zu konvertieren oder echte Entfernungen zu berechnen, da das OP einfach wissen möchte, ob die Koordinaten interpoliert werden können.

+0

Das sieht vielversprechend aus, wird es sofort testen. Ich sehe jedoch nicht die Relevanz der Zeit. Vielleicht hätte ich beschreibender sein sollen, aber die Orte sind bereits gespeichert und sortiert von den ältesten bis zu den neuesten, nicht im laufenden Betrieb angehängt. –

+0

Wenn das der Fall ist, ersetzen Sie einfach Zeit mit der ursprünglichen Indexnummer (nicht die komprimierte Indexnummer) – Grimxn