Teil 1 Problembeschreibung
1.1 Spezifische Aufgaben
Diese Arbeitsaufgabe ist die Flugbahnkomprimierung. Bei einer GPS -Daten Datensatzdatei enthält jeder Datensatz zwei Koordinatenfelder, Längengrad und Dimension. Alle Datensätze haben Breiten- und Längengradkoordinaten, um eine Flugbahn zu bilden. Es ist erforderlich, einen geeigneten Komprimierungsalgorithmus zu verwenden, damit der Entfernungsfehler der komprimierten Flugbahn weniger als 30 m beträgt.
1.2 Programmeingabe
Die Eingabe dieses Programms ist eine GPS -Daten Datensatzdatei.
1.3 Datenausgabe
Das Ausgabeformular ist eine Datei mit drei Teilen, der ID -Sequenz und der Koordinaten des Druckpunkts, der Anzahl der Punkte, des durchschnittlichen Entfernungsfehlers und der Kompressionsrate.
Antworten auf den zweiten Teil
Nach der Problembeschreibung lösen wir das Problem, und die Problemlösung ist in die folgenden Schritte unterteilt:
2.1 Datenvorverarbeitung
Diese Programmeingabe ist eine GPS -Daten Datensatzdatei mit insgesamt 3150 Datensätzen, und jede Datensätze ist in mehrere Felder unterteilt. Nach der Frage müssen wir nur auf die Längen- und Breitengrad -Koordinatenfelder achten. Einige Datensätze der ursprünglichen Datendatei sind in Abbildung 2.1 dargestellt:
Abbildung 2.1 schematisches Diagramm der Teilsätze der Originaldatendatei
As shown in Figure 2.1, the storage format of the latitude and longitude coordinate field data in each record in the original data file is a typical GPS coordinate expression method, that is, the degree division format, the form is dddmm.mmmmmm, where ddd represents degree, mm.mmmm represents fraction, the decimal point represents the integer part of the fraction, and the decimal point represents the decimal part of the fraction; In dieser Datenvorverarbeitung müssen wir die Berechnung des Abstands zwischen den nächsten beiden Koordinatenpunkten erleichtern, um die Daten der Breitengrad- und Längengradkoordinaten in der Gradteilungsformat in Form des Grades umzuwandeln. Die Umwandlungsmethode lautet DDD+mmmmm/60. Hier behalten wir die 6 Ziffern nach dem Dezimalpunkt, und die konvertierte Form ist ddd.xxxxxx.
Wir nehmen als Beispiel die Koordinaten für Breiten- und Längengradkoordinaten (11628.2491, 3955.6535). Das Konvertierungsergebnis ist (116.470818, 39,927558). Die Breiten- und Längengradkoordinaten in allen Datensätzen werden mit der Methode durchgeführt, und für jeden konvertierten Koordinatenpunkt kann eine ID generiert und eindeutig identifiziert werden. Nach der Komprimierung müssen wir nur die IDs aller reservierten Punkte ausgeben.
2.2 Douglas-Peucker-Trajektorienkomprimierungsalgorithmus
Trajektorienkomprimierungsalgorithmen sind in zwei Kategorien unterteilt, nämlich verlustfreie Komprimierung und verlustige Komprimierung. Verlustlose Komprimierungsalgorithmen umfassen hauptsächlich die Huffman -Codierung, und Verlustkomprimierungsalgorithmen werden in die Batch -Verarbeitungsmethode und die Online -Datenkomprimierungsmethode unterteilt. Die Batch-Verarbeitungsmethode umfasst den DP (Douglas-Peucker) -Algorithmus, den TD-TR (Top-Down-Zeitrate) -Algorithmus und der Bellman-Algorithmus. Zu den Online-Datenkomprimierungsmethoden gehören Gleitfenster, geöffnete Fenster, sichere ödenbasierte Methoden usw.
Aufgrund der begrenzten Zeit haben wir für diese Flugbahnkomprimierung beschlossen, einen relativ einfachen DP -Algorithmus zu verwenden.
Die Schritte des DP -Algorithmus sind wie folgt:
(1) Verbinden Sie eine gerade Linie AB zwischen zwei Punkten A und B am Anfang und am Ende der Kurve, und die gerade Linie ist der Akkord der Kurve;
(2) Überqueren Sie alle anderen Punkte auf der Kurve, finden Sie den Abstand von jedem Punkt zur geraden Linie AB, finden Sie den Punkt C mit dem maximalen Abstand und zeichnen Sie den maximalen Abstand als Dmax auf.
(3) Vergleichen Sie den Abstand Dmax mit der vordefinierten Schwellenwert -Dmax -Größe. Wenn dmax <dmax ist, wird die gerade Linie AB als Annäherung des Kurvensegments und das Kurvensegment verarbeitet;
(4) Wenn dmax> = dmax, sprengt Punkt C die Kurve AB in zwei Abschnitte AC und CB unterteilt und führt (1) bis (3) Schritte dieser beiden Abschnitte aus;
(5) Wenn alle Kurven verarbeitet werden, wird die von jedem Segmentierungspunkt gebildete Polylinie wiederum den Pfad der ursprünglichen Kurve angeschlossen.
2.3 Der Abstand von Punkt zu Linie
Im DP -Algorithmus müssen wir den Abstand von einem Punkt zu einer geraden Linie finden. Diese Entfernung bezieht sich auf die vertikale euroähnliche Entfernung, dh die Entfernung D von Punkt C außerhalb der geraden Linie AB zur Linie AB. Hier sind die Punkte A, B und C alle Breiten- und Längengradkoordinaten; Wir verwenden die gleichflächige Dreiecksmethode, um den Abstand zu finden. D. Die spezifische Methode ist: Punkte A, B und C bilden ein Dreieck. Es gibt zwei Möglichkeiten, den Bereich dieses Dreiecks zu finden, nämlich die gewöhnliche Methode (untere x Höhe/2) und die Helen -Formel. Die Helen -Formel lautet wie folgt:
Angenommen, es gibt ein Dreieck mit Seitenlängen A, B und C. Die Bereiche des Dreiecks können aus der folgenden Formel erhalten werden:
wobei P halb Umfang ist:
Wir können den Bereich des Dreiecks durch die Helen -Formel finden, und dann können wir die Größe der Höhe finden, wo die Höhe der Abstand d ist. Um die Helen -Formel zu verwenden, müssen Sie den Abstand zwischen drei Punkten A, B und C finden. Die Entfernungsformel wird vom Lehrer angegeben, und Sie können die Entfernungsfunktion direkt aufrufen.
Hinweis: Fügen Sie nach dem Finden der Entfernung den Absolutwert hinzu, um zu verhindern, dass der Abstand von negativ ist.
2.4 Lösen Sie den durchschnittlichen Fehler
Der durchschnittliche Fehler bezieht sich auf den Wert, der durch Teilen der Summe der Entfernungen von den Punkten, die während der Komprimierung in das entsprechende Liniensegment ignoriert wurden, durch die Gesamtzahl der Punkte geteilt.
2.5 Lösung zur Kompressionsrate
Die Komprimierungsverhältnisberechnung ist wie folgt:
2.6 Generierung von Datenergebnisdateien
Nach der obigen Verarbeitung und Berechnung schreiben wir die ID der verbleibenden Punkte nach der Komprimierung und die Anzahl der Punkte, den durchschnittlichen Entfernungsfehler, die Komprimierungsrate und andere Parameter in die Endergebnisdatei, und die Antwort auf die Frage wird abgeschlossen.
Teil 3 Code Implementierung
Dieses Programm ist in Java -Sprache mit der Entwicklungsumgebung der Intellij -Idee 14.0.2 geschrieben. Der Code ist in zwei Klassen unterteilt. Eines ist die ENPOINT-Klasse, die zum Speichern von Breiten- und Längenpunktinformationen verwendet wird, und die andere ist die Klasse der TrajektorienkompressionMain, die zum Schreiben von Funktionen wie Datenverarbeitung, DP-Algorithmus, Punkt-zu-Line-Distanz und durchschnittlicher Fehler verwendet wird.
3.1 Verfahrensprozess
Der gesamte Programmfluss enthält hauptsächlich die folgenden Schritte:
(1) Definieren Sie das zugehörige Array -Array- und Dateiobjekt, unter dem es drei ArrayList -Array -Objekte gibt, nämlich den ursprünglichen Breiten- und Längengrad -Koordinaten -Array -PGPSarryinit, das gefilterte Punktkoordinaten -Array -PGPsarrayFilter sowie das gefilterte und sortierte Punktkoordinaten -Array -PGPsRayFiltersort; Es gibt fünf Dateiobjekte, nämlich das ursprüngliche Datendateiobjekt FGPS, das komprimierte Ergebnis -Datendateiobjekt -OGPS, das DatendateifinitGPSpoint, das die konvertierten ursprünglichen Breitengrad- und Longitude -Koordinatenpunkte, die Simulationstest -Dateien ftestIntoint und fTestFilterpoint verwaltet.
(2) die Koordinaten des ursprünglichen Punkts erhalten und in die Datei schreiben, hauptsächlich zwei Vorgänge: Lesen der Datei und Schreiben der Datei;
(3) Flugbahnkompression durchführen;
(4) sortieren Sie die komprimierten Koordinaten mit Breitengraden und Längengradpunkten;
(5) Simulationstestdateien generieren und mit R -Sprach -Tools Grafiken zeichnen, um das Endergebnis zu erhalten.
(6) Ermitteln Sie den durchschnittlichen Fehler und die Komprimierungsrate, der durchschnittliche Fehler wird durch eine Funktion erhalten und die Komprimierungsrate wird direkt berechnet.
(7) Schreiben Sie das Endergebnis in die Ergebnisdatei, einschließlich der gefilterten Punkt -ID, der Anzahl der Punkte, der durchschnittlichen Fehler und der Komprimierungsrate;
3.2 spezifischer Implementierungscode
(1) enpoint.java
package cc.xidian.main;import java.text.DecimalFormat;/*** Created by hadoop on 2015/12/20.*/public class ENPoint implements Comparable<ENPoint>{public int id;//Point IDpublic double pe;//Longitude public double pn;//Dimension public ENPoint(){}//Empty constructor public String toString(){//DecimalFormat df = new DecimalFormat ("0,000000"); ID+"#"+this.pn+","+this.pe;} public String gettestString () {DecimalFormat df = new DecimalFormat ("0.0000000"; GetResultstring () {DecimalFormat df = new DecimalFormat ("0,000000"); return this.id+"#"+df.format (this.pn)+","+df.format (this.pe);}@überredepublic int -Vergleiche (umgegebene andere) {id (this.id). sonst wenn (this.id> other.id) return1; Elsereturn0;}}(2) TrajektorienkompressionMain.java
Paket cc.xidian.main; import Java.io.*; import Java.text.decimalformat; Import Java.util. Ausnahme {//. ArrayList <Enpoint> (); // Originaler Datensatz und Längengrad -Koordinaten -Array -ArrayList <Enpoint> pgpsarrayFilter = new ArrayList <enpoint> (); // gefilterte Breitengrad- und Längengrad -Koordinate -Array -Array -Arraylist <Noint> pgpsarrayFiltersort = new Arraylist <enpoint <). Datei ("2007-10-14-gps.log"); // Original Datendatei-Objektdatei OGPS = New Datei ("2015-12-25-GPS-result.log"); // gefilterte Ergebnisdatendatei-Objekt // Halten Sie den ursprünglichen Breitengraddatendatei und die Longgröitude-Datendatei, die latgritude data-datei konvertiert wurden, die Format- und Longgrößenwert-Wert-Wert-Wert- und Latgradedwert-Wert, die und das Latgradedwert, und das Latgradedwert, das Wert und die Latgradedwert. 6-stellige Zahlen nach der Dezimalpunktdatei FinitGPSpoint = neue Datei ("2007-10-14-GPS-Enpoint.log"); // Die konvertierte Datendatei des ursprünglichen Breitengrad-Koordinatenpunkts nach der konvertierten Datei ftestinitpoint = new Datei ("2007-14-GPS-IntittestPoint-FTESTIGE-DATEIL LATEGEDLAGEL LATEGEDLAGEL. Datei ("2015-12-25-GPS-FilterTestPoint.log"); // verwendet für die Datei der gefilterten Breiten- und Longitude-Koordinatenpunktdata nachher simulation//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pgpsarrayinit); // Schreiben Sie die konvertierten Original- und Längengrad -Punkt -Daten in das Dateisystem.out.println (pgpsarrayinit.size (); // Ausgabe der Anzahl der ursprünglichen Breitengrad- und Längengradspitze ausgeben coordinates//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 30.0;//Set the maximum distance error threshold pGPSArrayFilter.add(pGPSArrayInit.get(0));//Get the coordinates of the first original latitude and longitude point and add them to the filtered array pGPSArrayFilter.add(pGPSArrayInit.get(pGPSArrayInit.size()-1));//Get the coordinates of the last original Breitengrad- und Längenpunktpunkt und fügen Sie sie dem gefilterten Array Enpinit = New Enpoint [pgpsarrayinit.size ()]; // Verwenden Sie ein Punktarray, um alle Punktkoordinaten für den nachfolgenden Kompressionsiterator zu empfangen. = iinit.Next (); jj ++;} // Die Koordinaten des Punktes in ArrayList in das Punktarray int start = 0; // start-subscript int End = pgpsarrayinit.size ()-1; // End-Subscript trajcompressc (enpinit, pgpsrayfilter, start, end, dmax); System.out.println (pgpsArrayFilter.size ()); // Ausgabe komprimiert points//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Enpoint [pgpsarrayfilter.size ()]; // Verwenden Sie ein Array von Punkten, um gefilterte Punktkoordinaten zu empfangen, für den folgenden Sortier -Iterator <enpoint> if = pgpsarrayFilter.iterator (); int i = 0; while (if.hasnext () {{ENPFILTER -WARTE -AUSGEBEHALT. point array arrays.sort (enpFilter); // sortieren für (int j = 0; j <enpFilter.length; j ++) {pgpsarrayFiltersort.add (enpfilter [j]); // Schreiben Sie die sortierten Punktkoordinaten in eine Neuanordnung. array}//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pgpsarrayFiltersort); // Schreiben Sie die gefilterten Breiten- und Längengrad -Datenpunkte in die Simulationsdatei. Das Format ist "Längengrad, Dimension". // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- getMeandisterRor (pgpsarrayinit, pgpsarrayFiltersort); // den durchschnittlichen Fehler finden System.out.println (Mderror); // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- (doppelte) pgpsarrayfilter.size ()/pgpsarrayinit.size ()*100; // Finden Sie die Komprimierungsrate System.out.println(cRate);//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- und Kompressionsverhältnis WriteFilterpointToFile (OGPS, pgpsArrayFiltersort, Mderror, Kiste); // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @param fgps: Quelldatendatei* @return pgpsArrayInit: return ArrayList -Array, das alle Punktkoordinaten speichert ArrayList <Enpoint> (); if (fgps.exists () && fgps.isfile ()) {InputStreamReader read = new InputStreamReader (neuer FileInputStream (fgps)); BufferedReader Breader = new BufferedReader (read); String str; String [] strgps; int i = 0; breader.readline ())! pgpsarray;}/*** Funktion Funktion: Schreiben Sie die Koordinaten des Breitengrads und der Längengrad, der durchschnittliche Entfernungsfehler und das Komprimierungsverhältnis des gefilterten Punkts zur Ergebnisdatei* @param outgpsFile: Ergebnisdatei* @param pgpppointFilter: Filtered Point* @Param Mderror: Durchschnittliche Entfernungsfehler* @Param Crate: Kompressionsverhältnis* @Throws AUSBIL WriteFilterpointToFile (Datei -OutgpsFile, ArrayList <Noint> pgppointFilter, doppelter Mderror, Doppelkiste) löst eine Ausnahme aus {iterator <enpoint> ifilter = pgpSpointfilter.iterator (); ifilter.next (); String sfilter = p.getResultstring ()+"/n"; byte [] bfilter = sfilter.getBytes (); rfilter.write (bfilter);} String strmc = "#"+Integer.toString (pgppointFilter.size ())+","+double.toString (mDerror)+","+double.toString (Kiste)+"%"+"#"+"/n"; Byte [] bmc = strmc.getBytes (); rfilter.write (BMC); pgppointfilter) löst die Ausnahme aus {iterator <enpoint> ifilter = pgpppointfilter.Iderator (); randomAccessfile rfilter = new randomaccessfile (outgpsFile, "rw"); while (ifilter.hasnext () {enpoint p = ifilter.next (); bfilter = sfilter.getBytes (); rfilter.write (BFilter);} rfilter.close ();}/*** Funktion: Schreiben Sie den Längengrad -Punkt -Koordinatendaten im Array in die Testdatei für visuelle Tests* @Param OutgpsFile: File -Objekt. WriteTestPointToFile (Datei -OutgpsFile, ArrayList <Enpoint> pgppointfilter) löst Ausnahme aus {Iterator <Enpoint> ifilter = pgppointfilter.iterator (); RandomAccessfile rFilter = new randomAccessfile (OutgpsFile, "rw"); sfilter = p.gettestString ()+"/n"; byte [] bfilter = sfilter.getBytes (); */public static double dftodu (String str) {int indexd = str.Indexof ('.'); String strm = str.Substring (0, Indexd-2); String Strn = StR.Substring (Indexd-2); Double d = double.ParsedoUlble (strm)+doppelt. @param d: Original -Doppelnummer*@return return die konvertierte Doppelnummer Verwenden der Helen -Formel). px)); double c = math.abs (Geodist (pb, px)); Doppel p = (a+b+c) /2.0; incomprehensible* @param pA: Start point* @param pB: End point* @return distance: Distance*/public static double geoDist(ENPoint pA,ENPoint pB){double radLat1 = Rad(pA.pn);double radLat2 = Rad(pB.pn);double delta_lon = Rad(pB.pe - pA.pe);double top_1 = Math.cos(radLat2) * Math.sin(delta_lon);double top_2 = Math.cos(radLat1) * Math.sin(radLat2) - Math.sin(radLat1) * Math.cos(radLat2) * Math.cos(delta_lon);double top = Math.sqrt(top_1 * top_1 + top_2 * top_2);double bottom = Math.sin(radLat1) * Math.sin (radlat2) + math.cos (radlat1)* math.cos (radlat2)* math.cos (Delta_lon); double delta_sigma = math.atan2 (ober, boden); Doppelentfernung = Delta_Sigma* 6378137.0; Radian*/public static double rad (double d) {return d* math.pi/180.0;}/*** Funktion Funktion: Gemäß der maximalen Entfernungsgrenze wird die ursprüngliche Trajektorie rekursiv unter Verwendung der DP -Methode DP -Methode, um das komprimierte Trajektory @param Enpinit zu erhalten: Original -Koordinaten -Archinat -Archinat -Archinat -Archat -Archat -Archat -Archat -Archat -Archat -Argumat -Arga -@Param -Tray @Param @Param. START: START -SABSCRIPS* @PARAM END: Endpunkt -Eintrag* @param dmax: Vorgegebener maximaler Entfernungsfehler*/public static void trajcompressc (enPoint [] enpinit, arrayList <enpoint> enparrayFilter, int start, int end, double dmax) {if (start <end) {// // recursive Zustand doppelter Maxdist = 0; 0;//Current subscript for (int i=start+1;i<end;i++){double curDist = distToSegment(enpInit[start],enpInit[end],enpInit[i]);//Distance from the current point to the corresponding line segment if(curDist > maxDist){maxDist = curDist;cur_pt = i;}//Finding the subscript of the maximum distance and the Entsprechender Punkt des maximalen Abstand Trajcompressc (enpinit, enparrayfilter, start, cur_pt, dmax); Koordinaten* @Return: RECHEN SIE DIE DEMAHRENEN Distanz*/public static double getMeandisterRor (ArrayList <enpoint> pgpsarrayInit, ArrayList <Enpoint> pgpsarrayFilterSort) {double sumdist = 0.0; für (int i = 1; i <pgpsarrayFiltersort.size (); pgpsarrayFilterSort.get (i-1) .id; int end = pgpsarrayFilterSort.get (i) .id; für (int j = start+1; j <end; j ++) { sumdist/(pgpsarrayinit.size ());TEIL IV -Verfahrensergebnisse
4.1 Ergebnisse der Programmausgabe
Komprimierte Ergebnisse:
(1) Gesamtzahl der Punkte: 140 Punkte; (2) durchschnittlicher Entfernungsfehler: 7,943786; (3) Druckrate: 4,4444%
4.2 Simulationsergebnisse
Nach der Komprimierung der Trajektorien konvertieren wir die ursprünglichen Koordinatenpunkte der Breite und Länge in komprimierte und gefilterte Breitengrad- und Längengrad -Koordinatenpunkte. Wir schreiben diese beiden Punkte koordinieren Daten in zwei Dateien und zeichnen die Trajektorien vor und nach der Komprimierung gemäß diesen beiden Dateien und vergleichen sie. Basierend auf den Vergleichsergebnissen können wir sehen, ob unser Trajektorienkomprimierungsalgorithmus wirksam ist. Das endgültige Vergleichsergebnis ist in Abbildung 4.1 dargestellt:
Zusammenfassung von Teil 5
Während des Schreibprozesses dieses Programms habe ich auf verschiedene Probleme gestoßen und viel Programmeerfahrung gelernt. Das Folgende ist eine Zusammenfassung der Probleme und Lösungen, die auftreten, und legte schließlich Verbesserungsvorschläge für die Mängel des Programms vor.
5.1 Probleme und Lösungen auftreten
Frage 1: Ausgabe des Breiten- und Längengradkoordinatenreihenfolge
Lösung: Die Parameter in der Entfernungsformel sind, dass sich der Breitengrad vor und der Längengrad hinten befindet und die Reihenfolge der Breiten- und Längengrad -Koordinatenpunkte angepasst werden müssen.
Frage 2: Die Entfernung kann nicht negativ sein
Lösung: Stellen Sie sicher, dass der gefundene Abstand nicht negativ sein kann, eine absolute Wertfunktion.
Frage 3: Implementierungsdetails der DP -Algorithmus
Lösung: Ich habe angefangen, das Array von ArrayList zu verwenden, um das Indexproblem zu lösen. Es gab einen großen Fehler beim rekursiven Lösen. Später wechselte ich zur Verwendung ordentlicher Array -Indexs für die Rekursion, und das Ergebnis war viel besser.
5.2 Bestehende Mängel und Aussichten
(1) Bei der Durchführung der Trajektorienkompression ist der DP -Algorithmus der einfachste Algorithmus und nicht der beste. Einige Algorithmen mit guten Ergebnissen können verwendet werden, um die Flugbahnkomprimierung erneut durchzuführen.
(2) Die Datenaufzeichnungen dieses Experiments betragen 3.150 und die Datenmenge ist nicht groß. Was soll ich tun, wenn es 1 Milliarde Daten gibt? Wir können Hardware, verteilte, Datenvorverarbeitung, Datensegmentierung und Data Warehouses mit guter Leistung in Betracht ziehen.
Das obige ist der vollständige Inhalt dieses Artikels über den detaillierten Code des Douglas-Peucker-Algorithmus für die Java-Programmierung zur Implementierung der Trajektorienkomprimierung. Ich hoffe, es wird für alle hilfreich sein. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!