diesmal mein patch direkt ins Forum. Dann landet auch nichts im Spamfilter
Ich habe meinen Logger so eingestellt, dass er abhängig der Geschwindigkeit einen Logpunkt speichert. Das Problem dabei ist, dass das relativ viele Punkte werden. Mit den Filtern, die Du bis jetzt implemntiert hast, lassen die sich nicht sehr gut rausfiltern. Da ich zuletzt etwas über den Douglas-Peucker-Algorithmus zur Punktausdünnung gelesen habe, habe ich diesen in Routeconverter eingebaut. Damit konnte ich in meinen Test die Wegpunktliste erheblich verringern, vorallendingen bei geraden Strecken.
Ich habe von allen betroffenden Dateien einen Patch erstellt, damit Du die Daten einpflegen kannst. Da ich nicht Deinen GUI-Designer habe, konnte ich den Filter nicht mit auf den Filterdialog setzen. Dies müsstest Du noch erledigen. Es ist ein Eingabefeld für den Schwellenwert notwendig.
Beim Testen mit größeren Wegpunktlisten (>1000) ist mir aufgefallen, dass Routeconverter nach dem Markieren und Löschen die Karte meist nicht mehr aktualisiert hat. Er fängt wohl noch an die ersten markierten Wegpunkte auf der Karte anzuzeigen, dass wars dann aber.
Ich denke mal dieser Patch ist für das Programm interessanter als meine letzte Ergänzung mit dem Speedtrack und Kilometermarken.
Ich hatte immer wieder das Problem, dass der View hängen geblieben ist. Vorallendingen, wenn man mehrere Positionen löscht. Da ich dann aber auch noch festgestellt habe, dass manche Extrempunkte gar nicht mit ausgegeben werden und auch die Anzeige bei sehr vielen Punkten extrem langsam bis unbedienbar wird, habe ich mich entschlossen da noch etwas mehr dran zu machen.
Die Anzeige verwendet jetzt je nach Zoomlevel erheblich weniger Routenpunkte. Damit wird alles etwas schneller. Auch ein Bug beim Markieren habe ich beseitigt.
Falls Du nicht alles von mir übernehmen willst, solltest Du wenigstens den Teil beim Löschen der Punkte übernehmen. Das Problem dort besteht darin, dass ein Script nicht mehr ausgeführt wird. Bei mir reproduzierbar: In einer großen Punkteliste (ca. 10.000 Punkte) 10 Einträge markieren, dann noch einen dazu und es wird auf der Karte nichts mehr aktualisiert. Programm läßt sich dann nur noch abschießen. Behoben wird das Problem, wenn man erst das Script mit dem Löschen der Punkte ausführt und dann das neu Setzen. (MapView.selectPositions)
EddiVonDerAlm Wrote:Die Anzeige verwendet jetzt je nach Zoomlevel erheblich weniger Routenpunkte. Damit wird alles etwas schneller. Auch ein Bug beim Markieren habe ich beseitigt.
Hallo Eddi/Malte,
ich bin begeistert!
Vielen Dank für den Patch, Du löst damit ein paar Probleme, die ich schon länger vor mir herschiebe:
das Zeichnen der Karte war viel zu langsam
beim Löschen hängt sich das Zeichnen auf
der Douglas Peucker Algorithmus ist viel besser als meine hemdsärmeligen Varianten
EddiVonDerAlm Wrote:Falls Du nicht alles von mir übernehmen willst, solltest Du wenigstens den Teil beim Löschen der Punkte übernehmen. Das Problem dort besteht darin, dass ein Script nicht mehr ausgeführt wird. Bei mir reproduzierbar: In einer großen Punkteliste (ca. 10.000 Punkte) 10 Einträge markieren, dann noch einen dazu und es wird auf der Karte nichts mehr aktualisiert. Programm läßt sich dann nur noch abschießen. Behoben wird das Problem, wenn man erst das Script mit dem Löschen der Punkte ausführt und dann das neu Setzen.
Ich habe alles übernommen, nicht 1:1 sondern in meinem Codestyle und Namen, die m.E. besser zum restlichen Code passen. Synce mal die Revisionen 877 bis 880.
Und ich habe den Filterdialog erweitert, damit man mit dem Douglas Peucker Algorithmus filtern kann. Angefangen hattest Du das ja in BaseRoute.
// TODO what does that do?
double width = northEast.getLongitude() - southWest.getLongitude();
double height = southWest.getLatitude() - northEast.getLatitude();
northEast.setLongitude(northEast.getLongitude() + width);
northEast.setLatitude(northEast.getLatitude() - height);
southWest.setLongitude(southWest.getLongitude() - width);
southWest.setLatitude(southWest.getLatitude() + height);
List<BaseNavigationPosition> result = new ArrayList<BaseNavigationPosition>();
result.add(positions.get(0));
for (int i = 1; i < positions.size(); i++) {
BaseNavigationPosition position = positions.get(i);
if (Calculation.containsPosition(northEast, southWest, position)) {
result.add(position);
}
}
return result;
}
Was bezweckt die Berechnung von width und height sowie das Addieren und Subtrahieren?
routeconverter Wrote:Ich habe alles übernommen, nicht 1:1 sondern in meinem Codestyle und Namen, die m.E. besser zum restlichen Code passen. Synce mal die Revisionen 877 bis 880.
Mit den Änderungen habe ich überhaupt kein Problem. Wenn ich mir jetzt Deine Variablen- und Methodenamen ansehe, sind die schon besser zu lesen. Ich habe da so ein bisschen Probleme... mein englisch reicht zum Lesen, aber schreiben/sprechen muss ich eigentlich nie was und da fehlt mir dann der aktive Wortschatz. Vielleicht bekomme ich das mal hin, bis jetzt konnte ich mich noch nicht dazu überwinden das Manko zu beheben. Wenn man es fast nie braucht ... dann ist es so wie mit dem guten Pferd, dass springt auch immer nur so hoch wie die Latte hängt. Auch die Javaspracherweiterungen ab 1.4 laufen mir nicht so flüssig von der Hand...
routeconverter Wrote:Was mir noch nicht gefällt ist MapView#filterVisiblePositions()
...
Was bezweckt die Berechnung von width und height sowie das Addieren und Subtrahieren?
Das Ziel ist nur die Punkte für den aktuell sichtbaren Ausschnitt anzuzeigen, da man dann aber bei einer Verschiebung der Karte sofort keine Route mehr sieht, habe ich den Routenbereich der gezeichnet wird in alle Richtungen vergrößert.
Allerdings habe ich gerade gesehen, dürfte das auch noch zu einem Fehler führen. Es werden nur die Punkte angezeigt die auch wirklich in diesem Bereich liegen. Korrekterweise müsste man prüfen, ob eine Strecke durch das gerade sichtbare Mapfenster läuft und auch dann anzeigen. Wenn man z.Z einen Punkt in Hamburg setzt und den anderen in Hannover, würde beim Reinzoomen in die Karte, die Strecke nicht mehr angezeigt werden.
Eine weitere Idee beim Zeichnen hätte ich auch noch. Ich bin aber noch nicht dazu gekommen es umzusetzen. Statt die Routenlinie erst zu löschen um sie dann neu zu Zeichnen könnte man auch erst neu Zeichnen und dann die alte Löschen. Das hätte den Vorteil, dass das kurze Verschwinden der Route nicht mehr sichtbar wäre.
Ich habe die neue Version 1.22.3 kurz getestet und ich finde die aktuelle Umsetzung des Douglas Peucker Algorithmus nicht gut. Das Problem dabei ist, dass der Algo aktuell nicht auf Entfernungen Rücksicht nimmt und schon geglättete Routen (z.B. gpsbabel: -x position,distance=5m,all,time=900 -x simplify,error=2m) weiter stark vereinfacht. Diese werden dann in der Karte viel zu grob dargestellt.
mrg21 Wrote:Ich habe die neue Version 1.22.3 kurz getestet und ich finde die aktuelle Umsetzung des Douglas Peucker Algorithmus nicht gut. Das Problem dabei ist, dass der Algo aktuell nicht auf Entfernungen Rücksicht nimmt und schon geglättete Routen (z.B. gpsbabel: -x position,distance=5m,all,time=900 -x simplify,error=2m) weiter stark vereinfacht. Diese werden dann in der Karte viel zu grob dargestellt.
Danke für den Hinweis. Daran habe ich gar nicht gedacht, da ich nicht mit durch gpsbabel geglätteten Routen arbeite. Der derzeitige Code
Code:
private static int[] douglasPeuckerSimplify(List<? extends BaseNavigationPosition> positions, int from, int to, double threshold) {
// find the point with the maximum distance
BaseNavigationPosition pointA = positions.get(from);
BaseNavigationPosition pointB = positions.get(to);
int maximumDistanceIndex = -1;
double maximumDistance = 0.0;
for (int i = from + 1; i < to; i++) {
double d = Math.abs(positions.get(i).getOrthogonalDistance(pointA, pointB));
if (d > maximumDistance) {
maximumDistance = d;
maximumDistanceIndex = i;
}
}
// if max distance is greater than threshold, recursively simplify
if ((maximumDistanceIndex != -1) && (maximumDistance > threshold)) {
int[] res1 = douglasPeuckerSimplify(positions, from, maximumDistanceIndex, threshold);
int[] res2 = douglasPeuckerSimplify(positions, maximumDistanceIndex, to, threshold);
function DouglasPeucker(PunkteListe[], epsilon)
// Punkt mit dem maximalen Abstand ermitteln
dmax = 0
index = 0
for i = 2 to (length(PunkteListe) - 1)
d = OrthogonalerAbstand(PunkteListe[i], Strecke(PunkteListe[1], PunkteListe[end]))
if d > dmax
index = i
dmax = d
end
end
// Abstand prüfen und ggf. in das Ergebnis eintragen
if dmax >= epsilon
// rekursiver Aufruf
rekErgebnis1[] = DouglasPeucker(PunkteListe[1...index], epsilon)
rekErgebnis2[] = DouglasPeucker(PunkteListe[index...end], epsilon)
// Bilden der Ergebnisliste
ErgebnisListe[] = {rekErgebnis1[1...end-1] rekErgebnis2[1...end]}
else
ErgebnisListe[] = {PunkteListe[1], PunkteListe[end]}
end
// Ergebnis zurückgeben
return ErgebnisListe[]
end
routeconverter Wrote:Was mir noch nicht gefällt ist MapView#filterVisiblePositions()
...
Was bezweckt die Berechnung von width und height sowie das Addieren und Subtrahieren?
Das Ziel ist nur die Punkte für den aktuell sichtbaren Ausschnitt anzuzeigen, da man dann aber bei einer Verschiebung der Karte sofort keine Route mehr sieht, habe ich den Routenbereich der gezeichnet wird in alle Richtungen vergrößert.
Das verstehe ich. Im Prinzip vergrößerst Du den Bereich, in dem Positionen noch berücksichtigt werden, auf das 3-fache. Aber nur für Tracks und nur wenn mehr als 1500 Positionen im Track sind. Reicht der Faktor 3 aus?
EddiVonDerAlm Wrote:Eine weitere Idee beim Zeichnen hätte ich auch noch. Ich bin aber noch nicht dazu gekommen es umzusetzen. Statt die Routenlinie erst zu löschen um sie dann neu zu Zeichnen könnte man auch erst neu Zeichnen und dann die alte Löschen. Das hätte den Vorteil, dass das kurze Verschwinden der Route nicht mehr sichtbar wäre.
Versucht habe ich das schon, doch die Google Maps API wird schnell instabil, wenn man zuviele Objekte benutzt.
Ich bin den Rest des Monats unterwegs und werde nicht dazu kommen, weiter daran zu arbeiten. Tob' Dich aus ;-) Patches sind immer willkommen.
Übrigens: Was sagst Du zum Einwand von mrg21 was bereits geglättete Routen angeht?
Hinter dem gpsbabel Parameter "-x simplify,error=2m" steckt angeblich auch der Douglas Peucker Algorithmus und bei diesem wird der threshold als Entfernung angegeben (error=2m).
Quick-and-Dirty Vorschlag: Routen kleiner 700 Trackpunkte nicht glätten.
mrg21 Wrote:Hinter dem gpsbabel Parameter "-x simplify,error=2m" steckt angeblich auch der Douglas Peucker Algorithmus und bei diesem wird der threshold als Entfernung angegeben (error=2m).
Quick-and-Dirty Vorschlag: Routen kleiner 700 Trackpunkte nicht glätten.
Der threshold ist bei RouteConverter abhängig vom ZoomLevel. Dies ist die Tabelle mit Threshold in Metern / 2500 pro Zoomlevel. Größter Zoomlevel zuerst.