x

POIs/Polylines nur je Kartenausschnitt laden


  1. POIs/Polylines nur je Kartenausschnitt laden · Ghostrider82 (Gast) · 15.02.2013 11:07 · [flux]

    Hallo zusammen,

    ich habe hier im Forum vor einiger Zeit einmal einen Beitrag gefunden der recht gut veranschaulichte, wie man realisieren kann, dass POIs oder Polylines dynamisch aus einer DB geladen werden und zwar immer in Abhängigkeit des Kartenabschnitts, so dass tatsächlich nur die relevanten Daten geladen werden. Da ich mit GPX Tracks arbeite, die sehr lang werden, habe ich das bisher so gelöst, dass ich nur Marker setze. Das hat mit einem hier gefundenen Hinweis/Beitrag sehr gut geklappt. Allerdings würde ich das nun gerne einmal mit einer Polyline versuchen, aber mir fehlt hier irgendwie der richtige Ansatz bzw. Einsprungspunkt.

    Kennt jemand ein Beispiel oder hat einen Rat, den ich mir mal zu Gemüte führen kann?

    Danke im Voraus - und einen schönen Start ins Wochenende 🙂


    • Re: POIs/Polylines nur je Kartenausschnitt laden · wambacher (Gast) · 15.02.2013 12:45 · [flux]

      Ghostrider82 wrote:

      Kennt jemand ein Beispiel oder hat einen Rat, den ich mir mal zu Gemüte führen kann?

      Mein Rat ist, dass du erstmal ein Beispiel lieferst 😉 Ohne zumindest etwas davon zu wissen, wie dein Umfeld aussieht, kann dir wohl niemand helfen.

      - Web-Anwendung mit Openlayers oder Leafleat?
      - Rendern eigener Karten mit Mapnik & Co ?
      - iPhone- oder Android-APP?
      - ???
      - ???

      danach gehts weiter:
      - wo sind die Daten?
      - wie greifst du drauf zu
      - ???

      Gruss
      Walter

      wenn es eine Openlayers-Anwendung mit einer DB auf dem eigenen Server wäre:

      ␣␣␣␣␣var␣pcnodes␣=␣new␣OpenLayers.Layer.Vector("Nodes",␣{
      displayInLayerSwitcher:␣true,
      isBaseLayer:		false,
      visibility:		true,
      numZoomLevels:		19,
      permalink:␣		"nodes",
      maxResolution:␣		resolutions[14],
      projection:		projfrom,
      strategies:		[new␣OpenLayers.Strategy.BBOX({ratio:␣1,␣resFactor:␣1.1})],
      protocol:		new␣OpenLayers.Protocol.HTTP({
      url:		"getPostalCodeNodes",
      format:		new␣OpenLayers.Format.GeoJSON()
      })
      });
      

      Wichtige Punkte:

      - OpenLayers.Layer.Vector
      - OpenLayers.Strategy.BBOX
      - OpenLayers.Format.GeoJSON()

      Am Server kommt dann so eine Query an: http://localhost:8080/getPostalCodeNodes/?bbox=8.0804583530426,50.104261318697,8.115112493515,50.116728784895
      d.h. openlayers fügt selber die bbox ein
      Mein Server schickt dann das Ergebnis im json-Format zurück und Openlayers macht den Rest.

      Gruss
      Walter


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 15.02.2013 13:11 · [flux]

      Nahmd,

      Ghostrider82 wrote:

      Da ich mit GPX Tracks arbeite, die sehr lang werden, habe ich das bisher so gelöst, dass ich nur Marker setze. Das hat mit einem hier gefundenen Hinweis/Beitrag sehr gut geklappt. Allerdings würde ich das nun gerne einmal mit einer Polyline versuchen, aber mir fehlt hier irgendwie der richtige Ansatz bzw. Einsprungspunkt.

      Kennt jemand ein Beispiel oder hat einen Rat, den ich mir mal zu Gemüte führen kann?

      Du suchst das hier. Es benutzt die von Wambacher vorgeschlagen Klassen “OpenLayers.Layer.Vector” und “OpenLayers.Strategy.BBOX”, dann aber “OpenLayers.Format.GPX” statt “OpenLayers.Format.GeoJSON”, was den Ablauf im Browser ein wenig verlangsamt.

      Da im schlimmsten Falle (zoom=0) die BBOX die ganze Welt umfasst, würden in diesem Fall immer *alle* Punkte der Linie übertragung, was spätestens bei 100000 Stück den Browser verstimmt. Deshalb lasse ich den Server – listig, listig – nur eine Auswahl der Punkte liefern: damit kann man einen beliebig langen Weg über alle Zoomstufen hinweg anzeigen.

      Nun zu den schlechten Nachrichten:

      1. ich habe die serverseitige Unterstützung nur als Perl-CGI vorlegen und nicht als PHP-Skript.
      2. ich will kann nicht bei der Zusammenstellung der Punkte zum Beispiel aus einer Relation helfen.

      Das erste Problem lässt sich allerdings lösen: durch Bestechung mit einer Tüte Gummibärchen oder (besser) durch das Versprechen, den Ablauf im Wiki zu dokumentieren.

      Gruß Wolf


    • Re: POIs/Polylines nur je Kartenausschnitt laden · wambacher (Gast) · 15.02.2013 13:31 · [flux]

      Netzwolf wrote:

      Deshalb lasse ich den Server – listig, listig – nur eine Auswahl der Punkte liefern: damit kann man einen beliebig langen Weg über alle Zoomstufen hinweg anzeigen.

      Eventuell noch "listiger":

      irgendwo␣weiter␣oben␣im␣html-code:
      
      var␣resolutions␣=␣␣␣␣␣␣␣[156543.03390625,␣78271.516953125,␣39135.7584765625,
      19567.87923828125,␣9783.939619140625,␣4891.9698095703125,
      2445.9849047851562,␣1222.9924523925781,␣611.4962261962891,
      305.74811309814453,␣152.87405654907226,␣76.43702827453613,
      38.218514137268066,␣19.109257068634033,␣9.554628534317017,
      4.777314267158508,␣2.388657133579254,␣1.194328566789627,
      0.5971642833948135];
      

      und dann das maxResolution: resolutions[14] aus dem obigen Beispiel und schon wird der Server gar nicht mehr belästigt, wenn das Zoomlevel kleiner als 14 ist.

      Kommt aber wohl auf die Zielsetzung an: Ich blende Daten bei kleineren Zoomstufen aus und Wolf schein die dann zu generalisieren. Auch ein schöner Ansatz. Man könnte bei punktförmigen Informationen auch clustern aber hier geht es ja um Ways.

      Gruss
      walter

      p.s. json hab ich nur als Beispiel genommen; gpx oder sogar osm geht auch, wenn man einen Server hat, der sowas liefern kann.


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 15.02.2013 13:41 · [flux]

      Nahmd,

      wambacher wrote:

      und dann das maxResolution: resolutions[14] aus dem obigen Beispiel und schon wird der Server gar nicht mehr belästigt, wenn das Zoomlevel kleiner als 14 ist.

      Wobei ich es gerade witzig finde, dass auf der Weltkarte der Weg noch zu sehen ist.
      Beim Hanseweg nur als Punkt, die E1, E4 & CO opder der Appalachian Trail sollten sehr schön zu sehen sein.

      p.s. json hab ich nur als Beispiel genommen; gpx oder sogar osm geht auch, wenn man einen Server hat, der sowas liefern kann.

      Json ist die beste Lösung, zum einen weil Du das über den fiesen “<script>-Befehl erzeugen”-Trick von einem anderen Server nachladen kannst – und das wird spätestens dann wichtig, wenn der OP mit einem Punktfilter ausgestattet wird –, und zum zweiten, weil (wenn man mutig genug ist, das json per eval() auszuwerten,) es deutlich schneller ist.

      Gruß Wolf

      Dass ich GPX benutzt habe, liegt – peinlich, peinlich, aber zum Glück liest das ja keiner – daran, dass ich das GPX-Format auswendig kenne, das Json aber hätte nachschlagen müssen.


    • Re: POIs/Polylines nur je Kartenausschnitt laden · wambacher (Gast) · 15.02.2013 14:46 · [flux]

      Netzwolf wrote:

      Json ist die beste Lösung, zum einen weil Du das über den fiesen “<script>-Befehl erzeugen”-Trick von einem anderen Server nachladen kannst – und das wird spätestens dann wichtig, wenn der OP mit einem Punktfilter ausgestattet wird –, und zum zweiten, weil (wenn man mutig genug ist, das json per eval() auszuwerten,) es deutlich schneller ist.

      da du ja auch mit postgresql und postgis arbeitest:

      select␣id,
      st_astext(linestring),
      ST_AsGeoJSON(linestring,5),
      ST_AsGeoJSON(ST_Centroid(linestring),5)
      from␣ways
      where␣id=99;
      
      99␣|␣LINESTRING(11.3661581␣48.1741769,11.366186␣48.1741419,11.3662301␣48.1741153,11.3662851␣48.1741004,11.3663747␣48.1741024,11.3664153␣48.1741169,11.3664584
      48.1741442,11.3664849␣48.1741796,11.3664895␣48.1742311,11.3664696␣48.1742684,11.3664317␣48.1742989,11.3663804␣48.1743189,11.3663076␣48.1743257,11.36625
      48.1743158,11.366201␣48.1742934,11.3661665␣48.1742612,11.3661506␣48.174223,11.3661581␣48.1741769)␣|
      
      {"type":"LineString","coordinates":[[11.36616,48.17418],[11.36619,48.17414],[11.36623,48.17412],[11.36629,48.1741],[11.36637,48.1741],[11.36642,48.17412],[11.36646,48.17414],
      [11.36648,48.17418],[11.36649,48.17423],[11.36647,48.17427],[11.36643,48.1743],[11.36638,48.17432],[11.36631,48.17433],[11.36625,48.17432],[11.3662,48.17429],[11.36617,48.17426],
      [11.36615,48.17422],[11.36616,48.17418]]}␣|
      
      {"type":"Point","coordinates":[11.36632,48.17421]}
      

      Noch einen kleinen json-Rahmen drum bauen, fertig. was will man mehr 😉

      Gruss
      walter


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 15.02.2013 15:05 · [flux]

      Nahmd,

      wambacher wrote:

      da du ja auch mit postgresql und postgis arbeitest:

      Nö. NOSQL-Datenbank.

      [...]snip[...]
      

      Mach das mal mit 100.000 Punkten. 😛
      Mit dem Browser von jemandem, den Du nicht leiden kannst.

      Guck Dir die Version ohne Preprocessing an:

      1. die kann (“Please zoom in to view data”, yeah!) nicht den Weg als Ganzes darstellen. Das ist Mist.

      2. das Ergebnis sieht suboptimal aus. Weil da ich weiss nicht wie viele einzelne Linien gezeichnet werden, und an der Stoßstelle von zwei teiltransparenten Linien ein Kreis mit geringerer Transparenz entsteht. Der Weg ist also mit Flecken gesprenkelt, die nichts mit der Route zu tun haben, sondern reine Artefakte aus der Struktur der Speicherung der Daten sind.

      Dafür wird dieser Wanderweg minutenaktuell dargestellt. Da kann ich wegen des Preprocessings nicht mithalten. Allerdings glaube ich auch nicht, dass die Routenführung minütlich geändert wird.

      Gruß Wolf


    • Re: POIs/Polylines nur je Kartenausschnitt laden · wambacher (Gast) · 15.02.2013 16:59 · [flux]

      Netzwolf wrote:

      Mach das mal mit 100.000 Punkten. 😛
      Mit dem Browser von jemandem, den Du nicht leiden kannst.

      sowas macht man doch nicht, dann wird geklustert. Bei 100k Nodes geht jeder Browser in die Knie.

      2. das Ergebnis sieht suboptimal aus. Weil da ich weiss nicht wie viele einzelne Linien gezeichnet werden, und an der Stoßstelle von zwei teiltransparenten Linien ein Kreis mit geringerer Transparenz entsteht.

      ganz banaler Vorschlag: opacity=1, da können sich noch so viel Kreise überlappen: blau bleibt blau, blauer wird's nicht.


    • Re: POIs/Polylines nur je Kartenausschnitt laden · mmd (Gast) · 15.02.2013 17:05 · [flux]

      .


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 15.02.2013 17:55 · [flux]

      Nahmd,

      wambacher wrote:

      Mach das mal mit 100.000 Punkten. 😛

      sowas macht man doch nicht, dann wird geklustert. Bei 100k Nodes geht jeder Browser in die Knie.

      Ich spreche nocht von 100.000 POIs, sondern von einer Linie mit 100.000 Punkten.

      Aber selbst, wenn es POIs-wären: die Cluster-Strategie hilft bei der Anzeige, wenn zu viele Objekte übereinandergezeichnet werden. Aber nicht beim Traffic und auch nicht bei der vom Browser zu handelnden Datenmenge. Probier es aus.

      2. das Ergebnis sieht suboptimal aus. Weil da ich weiss nicht wie viele einzelne Linien gezeichnet werden, und an der Stoßstelle von zwei teiltransparenten Linien ein Kreis mit geringerer Transparenz entsteht.

      ganz banaler Vorschlag: opacity=1, da können sich noch so viel Kreise überlappen: blau bleibt blau, blauer wird's nicht.

      <mode ironie="extrafies">
      Das ist korrekt.
      Weiterer Vorteil: man muss die blöden Straßennamen unter der Linie nicht mehr lesen.

      Ich ahne übrigens schon, was jetzt kommen wird: “dann machen wir die Linie halt nur 0.5 Pixel breit.”
      </mode>

      Es ist wirklich erstaunlich, welche Nachteile in Kauf genommen werden, nur um direkt mit OSM-Rohdaten arbeiten zu können.

      Gruß Wolf

      Edit: Ironiemarker eingefügt


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 15.02.2013 17:56 · [flux]

      Nahmd,

      mmd wrote:

      Preprocessing (z.B. Filterung, Vereinfachung, etc.) soll ja vom Hören sagen auch im Browser funktionieren, dafür braucht es nicht unbedingt einen eigenen Server.

      Das ist richtig.

      Der Browser ist aber nicht wirklich glücklich, wenn er erst einmal 100.000 Punkte (denn das Thema war: lange Tracks) abholen und bearbeiten darf.

      Das "Please zoom in to view data" dürfte wahrscheinlich am zu knapp gewählten (=fehlenden) Timeout in Jan's Beispiel hängen.

      Das ist nicht ganz richtig:

      if (this.layer && this.layer.map && this.layer.map.getZoom() < this.zoom_data_limit) {
      setStatusText("Please zoom in to view data.");
      zoom_valid = false;
      this.bounds = null;
      }

      Gruß Wolf


    • Re: POIs/Polylines nur je Kartenausschnitt laden · mmd (Gast) · 15.02.2013 18:30 · [flux]

      .


    • Re: POIs/Polylines nur je Kartenausschnitt laden · wambacher (Gast) · 15.02.2013 18:44 · [flux]

      Netzwolf wrote:

      Ich spreche nocht von 100.000 POIs, sondern von einer Linie mit 100.000 Punkten.

      ok, ich ab jetzt auch 😉

      Aber selbst, wenn es POIs-wären: die Cluster-Strategie hilft bei der Anzeige, wenn zu viele Objekte übereinandergezeichnet werden. Aber nicht beim Traffic und auch nicht bei der vom Browser zu handelnden Datenmenge. Probier es aus.

      hab ich längst und bin dann zum Clustern auf dem Server gewechselt. Und genau das hab ich bei meiner Antwort ("Cluster doch einfach") vergessen. 100k Nodes zum Browser hochzujagen und ihn dann bitten, das gefälligst zu clustern, ist wohl nix. Schwamm drüber.

      Weiterer Vorteil: man muss die blöden Straßennamen unter der Linie nicht mehr lesen.

      Ich ahne übrigens schon, was jetzt kommen wird: “dann machen wir die Linie halt nur 0.5 Pixel breit.”

      naja, ich denke mir mal <ironie>...</ironie> und dann passt das schon. 😉

      Es ist wirklich erstaunlich, welche Nachteile in Kauf genommen werden, nur um direkt mit OSM-Rohdaten arbeiten zu können.

      Ist ja nicht deine Schöpfung und Jan wird das auch irgendwann mal hinkriegen. Da hilft es wirklich nur, den Job dem Server zu überlassen.

      Gruss
      walter


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Ghostrider82 (Gast) · 19.02.2013 09:42 · [flux]

      Hallo zusammen,

      vielen Dank zunächst für die ausführlichen Informationen.

      Wie immer in diesen Forum hat das eine ganze Menge Licht ins Dunkel gebracht.

      @wambacher
      Sorry für meine spärliche Beschreibung meines Eingangsposts, das passiert, wenn man einen solchen Beitrag zwischen Tür und Angel schreibt -.-

      Grob gesagt: Hole Wegpunkte aus einer DB, und stelle diese auf einer Webseite als Linestring da.

      Beitrag #3 von Netzwolf hat aber im Grunde genau das aufgegriffen, was ich gesucht habe.
      Nachdem ich mir die OpenLayers.Format.GeoJSON sowie OpenLayers.Strategy.BBOX näher angeschaut habe - zumindest soweit um Verständnis dafür zu entwickeln, da dies Neuland für mich ist, konnte ich anfangen, mein Anliegen umzusetzen, zumal ich das GeoJSON auch an anderer Stelle sehr gut gebrauchen kann.

      Das weglassen von Daten je nach Zoomstufe ist natürlich eine nette Idee, schade, dass ich da nicht selbst drauf gekommen bin.
      Also eine kleine (zunächst zu Testzwecken) PHP Datei geschrieben, um zu schauen, was beim JSON Request an Daten übertragen wird.

      Dann anhand der "mindist" einen kleinen Filter definieren, welche Daten nach welchem Muster ignoriert werden sollen und wieviele.

      Bei mindist-31250 z.B. habe ich quasi ganz Europa auf dem Schirm, bei 10 Tracks, die jeweils 400.000 Werte umfassen, muss ich hier natürlich knallhart Daten "droppen", als Vorfilter schwebt mir hier vor nur jeden 10.000sten Datenpunkt in den Linestring einfließen zu lassen, was man prima mit Modulo lösen könnte.

      Wichtig ist, dass nicht erst xx-Tausend Werte am Browser ankommen, die dann dort prozessiert werden sollen, aber ich denke, das klappt mit oben gennanter Lösung sehr gut.

      Was mich jetzt an dieser Stelle aber interessieren täte ist, ob ich - das konnte ich beispielsweise meinen Recherchen zum Thema noch nicht entnehmen, auch Funktionen in Javascript implmentieren kann, als einfaches Beispiel z.B., dass ein Klick auf eine Linie einfach die Funktion alert aufruft und mir stupide die Koordinaten anzeigt. Gibt es für sowas einen Workaround?


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 19.02.2013 12:40 · [flux]

      Nahmd,

      Ghostrider82 wrote:

      Was mich jetzt an dieser Stelle aber interessieren täte ist, ob ich - das konnte ich beispielsweise meinen Recherchen zum Thema noch nicht entnehmen, auch Funktionen in Javascript implmentieren kann, als einfaches Beispiel z.B., dass ein Klick auf eine Linie einfach die Funktion alert aufruft und mir stupide die Koordinaten anzeigt. Gibt es für sowas einen Workaround?

      Zur Klasse “OpenLayers.Layer.Vector” gibt es die praktische Ergänzung “OpenLayers.Control.SelectFeature”. Die kümmert sich um sowas. Hier nur als Mouseover. Die kann aber auch Klick.

      Deinem Wunsch besser entspricht das hier (auf Track klicken). Die Implementierung ist aber uralt und Mist, das sollte heute viel einfacher mit Bordmitteln von Layer.Vector/Control.SelectFeature gehen.

      Gruß Wolf

      Edit: zweites Beispiel ergänzt.


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 19.02.2013 13:18 · [flux]

      Nahmd,

      mmd wrote:

      Der Browser ist aber nicht wirklich glücklich, wenn er erst einmal 100.000 Punkte (denn das Thema war: lange Tracks) abholen und bearbeiten darf.

      Das Laden der kompletten Relation braucht hier 30s und überträgt etwas mehr als 1 MB (Frage: woran das wohl liegt?). Der Browser lebt zwar noch, aber flott ist anders.

      Wenn ich was baue, setze ich ein Timelimit von 0.3s. Alles was darüber geht, braucht einen wirklich guten Grund. Und mehr als 1s ist völlig inakzeptabel. Vielleicht habe ich deshalb so heftig reagiert. Sorry. 🤔

      Da werden bestimmt noch alle Details im Speicher gehalten, obwohl man das meiste davon sicherlich schon längst hätte freigeben können für eine Ansicht in Level 8.

      Ich würd' da nicht üder das JS böse sein. Ich findes es absolut beeindrucken, wie schnell das heute ist. Auf der Höhenbeschränkungskarte ist das geradezu unglaublich. Also dem auch mal ein Hängen nachsehen. Und nicht mit mit überflüssigen Daten malträtieren 😉

      Das ist immer ein Trade off: wenn ich mir überlege, welchen (administrativen/Ressourcen/Zeit-)Aufwand man treiben muss, um mit einer aktuellen DB arbeiten zu können, nur um dort ein sauberes Preprocessing machen zu können, relativiert sich das ganze.

      Das braucht keine Datenbank. Die Daten kann man von OP oder (in diesem Fall) ganz trivial vom OSM-DB-Server ziehen (letzteres hatte ich gemacht). Der Aufwand ist gewiss nicht überzogen, wenn man damit ein Seite mit guter Usability erzeugt.

      Wanderwege sind hier wahrscheinlich ein schlechtes Beispiel, einmal rechnen pro Woche/Monat dürfte absolut ok sein.

      Auch einmal je Tag. Oder je Stunde. Nichts davon tut dem Server weh, von dem man die Daten zieht. Und auf dem Server des Nutzers braucht die Aufbereitung nur Sekunden.

      Dann tut es wohl auch ein Extrakt von Geofabrik einmal in der Woche.

      Genau das ist völlig überzogen. 🙂

      Ich frage mich gerade, ob es nicht mal Zeit für einen "PostGIS Turbo" wäre, also einer zentralen minutenaktuellen Planet-Datenbank, auf der man das eine oder andere einfach mal ausprobieren könnte. Also, ohne sich gefühlte 5 Tage Planet Laden antun zu müssen.

      Du kannst ein PostGIS mit Aktualisierung aufsetzen und Readonly-Zugriffe von außen anonym oder nach Registrierung oder mit dem OSM-Account erlauben. Ich kann auch hoch und heilig versprechen, dass es einen ersten Nutzer gibt. 🙂

      Gruß Wolf


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Ghostrider82 (Gast) · 21.02.2013 21:48 · [flux]

      Ich versuche gerade krampfhaft, dein GPX Beispiel nachzuvollziehen (http://www.netzwolf.info/kartografie/op … tracks.htm)

      Klappt, unterbringen von zusätzlichen Werte in der GPX Datei sowie Zugriff auf den entsprechenden Wert via feature.attributes['xyz'] klappt auch. Bis dahin schon einmal super.

      Aber ganz im Gegensatz zu deinem JSON Beispiel klappt das mit dem dynamischen Laden der Daten nicht mehr.

      In deinem JSON Beispiel wird beim Verschieben bzw. Ändern des Zooms wie gewünscht ein neuer Request erzeugt.

      Beim GPX Beispiel funktioniert dies jedoch nicht. Ist das grundsätzlich so vorgesehen?

      Liegt das am strategies: [new OpenLayers.Strategy.Fixed()] anstelle strategies: [new OpenLayers.Strategy.BBOX({resFactor: 1.0 })]?

      Denn tausche ich Fixed() gegen BBox(..) bleibt die Karte dunkel (Scriptfehler bekomme ich jedoch keine.

      Anbei meine verzweifelte Zusammenwürfelei:

      <html>
      <head>
      <meta␣http-equiv="Content-Type"␣content="text/html;␣charset=iso-8859-1"␣/>
      
      <title>Trackdecoder</title>
      
      <script␣type="text/javascript"␣src="http://www.openlayers.org/api/OpenLayers.js"></script>
      <script␣type="text/javascript"␣src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
      
      <!--==================================================================================
      "loadstatus.js"␣enthaelt␣die␣Definition␣der␣Klasse
      "OpenLayers.Control.LoadStatus".
      Diese␣Klasse␣implementiert␣eine␣Lade-Statusanzeige.
      Bitte␣kopiere␣die␣JavaScript-Datei␣auf␣den␣eigenen␣Server.␣Danke.
      In␣den␣mit␣"#######"␣markierten␣Zeile␣wird␣der␣LoadStatus␣aktiviert.
      ===================================================================================-->
      
      <script␣type="text/javascript"␣src="js/load.js"></script>
      
      <!--==================================================================================
      Erweiterung␣zum␣Format␣"GPX":␣liefere␣Liste␣aller␣Segmente.
      ===================================================================================-->
      
      <script␣type="text/javascript">
      OpenLayers.Format.GPX.prototype.extractSegment=␣function␣(segment,segmentType)␣{
      
      var␣points=this.getElementsByTagNameNS(segment,segment.namespaceURI,segmentType);
      var␣point_features=[];
      
      for␣(var␣i=0,len=points.length;i<len;i++){
      
      var␣point␣=␣points[i];
      var␣geo␣=␣new␣OpenLayers.Geometry.Point(point.getAttribute("lon"),point.getAttribute("lat"));
      point_features.push(geo);
      var␣attributes={};
      var␣attCount=0;
      
      for␣(var␣attrNode=point.firstChild;␣attrNode;␣attrNode=attrNode.nextSibling)␣{
      //alert(␣attrNode.text);
      if␣(attrNode.nodeType!=1)␣continue;
      var␣valueNode=attrNode.firstChild;
      if(valueNode.nodeType!=3&&valueNode.nodeType!=4)␣continue;
      var␣value␣=␣valueNode.nodeValue;
      //alert(attrNode.nodeName);
      switch␣(attrNode.nodeName)␣{
      
      case␣'ele':
      attributes.ele␣=␣Math.round(parseFloat(value));
      
      break;
      
      case␣'time':
      unixtime␣=␣Date.parse(value);
      attributes.time␣=␣unixtime␣?␣new␣Date␣(unixtime)␣:␣null;
      break;
      case␣'speed':
      attributes.speed␣=␣value;
      
      }
      attCount++;
      }
      if␣(attCount)␣geo.attributes=attributes;
      }
      return␣new␣OpenLayers.Geometry.LineString(point_features);
      };
      </script>
      
      <script␣type="text/javascript">
      //------------------------------------------------------------------------------------
      //	Die␣anonyme␣Onload-Function␣baut␣das␣Kartenobjekt␣aus␣Komponenten␣zusammen.
      //	An␣der␣mit␣"***"␣markierten␣Zeile␣tragen␣Sie␣die␣URL␣*Ihrer*␣GPX-Datei␣ein.
      //------------------------------------------------------------------------------------
      
      var␣map;
      
      window.onload␣=␣function␣()␣{
      
      //----------------------------------------------------------------------------
      //	Karte␣-␣der␣Name␣('map')␣muss␣mit␣der␣id␣des␣<div>␣uebereinstimmen.
      //----------------------------------------------------------------------------
      
      map␣=␣new␣OpenLayers.Map␣('map');
      
      //----------------------------------------------------------------------------
      //	Default-Koordinatensystem␣fuer␣alle␣Controls
      //----------------------------------------------------------------------------
      
      map.displayProjection␣=␣new␣OpenLayers.Projection('EPSG:4326');
      
      //----------------------------------------------------------------------------
      //	Steuerelemente
      //----------------------------------------------------------------------------
      
      map.addControl␣(new␣OpenLayers.Control.LayerSwitcher());
      map.addControl␣(new␣OpenLayers.Control.LoadStatus());		//#######
      
      map.addLayer␣(new␣OpenLayers.Layer.OSM.Mapnik("Mapnik"));
      
      //----------------------------------------------------------------------------
      //	Kartenlayer
      //----------------------------------------------------------------------------
      
      map.addLayer␣(new␣OpenLayers.Layer.OSM.Mapnik('Mapnik'));
      
      //----------------------------------------------------------------------------
      //␣␣␣␣␣␣Vector␣(GPX)␣Layer
      //	die␣Karte␣zoomt␣automatisch␣auf␣den␣Umriss␣des␣Tracks
      //----------------------------------------------------------------------------
      
      var␣track␣=␣new␣OpenLayers.Layer.Vector("Route",␣{
      
      strategies:␣[new␣OpenLayers.Strategy.Fixed()],
      
      protocol:␣new␣OpenLayers.Protocol.HTTP({
      
      url:␣"route.php",
      params:␣{
      format:␣'gpx',
      mindist:␣1e6
      },
      format:␣new␣OpenLayers.Format.GPX({
      
      extractWaypoints:␣true,
      extractRoutes:␣true,
      extractTracks:␣true,
      extractAttributes:␣true
      })
      }),
      
      moveTo:␣function␣(bounds,␣zoomChanged,␣dragging)␣{
      
      if␣(zoomChanged)␣{
      
      this.protocol.params.mindist␣=␣1000000␣/␣Math.pow(2,␣this.map.getZoom());
      alert(bounds);
      }
      
      OpenLayers.Layer.Vector.prototype.moveTo.apply(this,␣arguments);
      },
      
      style:␣{
      fillColor:␣"#000000",
      strokeColor:␣"#ffff00",
      strokeDashstyle:␣"#LTYPE",
      strokeWidth:␣5,
      strokeOpacity:␣1.0,
      pointRadius:␣5
      },
      
      zoomMapToMyBounds:␣function␣()␣{
      
      bounds␣=␣this.getDataExtent();
      if␣(bounds)␣{
      this.map.zoomToExtent(bounds);
      }␣else␣{
      this.map.zoomToMaxExtent();
      }
      }
      
      });
      
      track.events.register("loadend",track,track.zoomMapToMyBounds);
      map.addLayer␣(track);
      
      //-----------------------------------------------------------------
      //	Erzeuge␣Popup
      //-----------------------------------------------------------------
      
      function␣createPopup(feature)␣{
      
      //-----------------------------------------------------------------
      //	Position␣des␣Klicks␣in␣Kartenkoordinaten
      //-----------------------------------------------------------------
      
      var␣hotspot␣=␣this.map.getLonLatFromPixel(this.lastXy);
      
      //-----------------------------------------------------------------
      //	Suche␣nach␣naechster␣Feature-Geometrie-Komponente
      //-----------------------------------------------------------------
      
      var␣nearestComponent=null;
      var␣minDistance=null;
      
      //-----------------------------------------------------------------
      //	Iteriere␣über␣alle␣Komponenten
      //-----------------------------------------------------------------
      
      if␣(feature.geometry␣&&␣feature.geometry.components)␣{
      
      for␣(var␣i=0;␣i<feature.geometry.components.length;␣i++)␣{
      
      var␣component␣=␣feature.geometry.components[i];
      if␣(!component.attributes)␣{␣continue;␣}
      
      var␣distance=
      (hotspot.lon-component.x)*(hotspot.lon-component.x)+
      (hotspot.lat-component.y)*(hotspot.lat-component.y);
      
      if␣(minDistance!=null␣&&␣minDistance␣<␣distance)␣continue;
      
      nearestComponent=component;
      minDistance=distance;
      }
      }
      
      //-----------------------------------------------------------------
      //	Speichere␣Position␣der␣naechsten␣Komponente
      //-----------------------------------------------------------------
      
      if␣(nearestComponent)␣{
      
      hotspot.lat␣=␣nearestComponent.y;
      hotspot.lon␣=␣nearestComponent.x;
      }
      
      //-----------------------------------------------------------------
      //	Konvertiere␣nach␣Geographischen␣Koordinaten
      //-----------------------------------------------------------------
      
      var␣pos␣=␣hotspot.clone();
      if(this.displayProjection)␣{
      
      pos.transform(this.map.getProjectionObject(),this.displayProjection);
      }
      
      //-----------------------------------------------------------------
      //	Beginne␣Popup-<div>
      //-----------------------------------------------------------------
      
      text␣=␣'<div>';
      
      //-----------------------------------------------------------------
      //	Name␣des␣Features
      //-----------------------------------------------------------------
      
      text␣+=␣'<h3>'+feature.attributes.name+'<'+'/h3>\n';
      
      //-----------------------------------------------------------------
      //	Weitere␣Attribute␣des␣Features
      //-----------------------------------------------------------------
      
      if␣(feature.attributes)␣␣{
      
      for␣(var␣tag␣in␣feature.attributes)␣{
      
      if␣(tag␣!=␣'')␣{
      text␣+=␣tag+':␣'+feature.attributes[tag]+'<br␣/>\n';␣␣␣␣//
      document.getElementById('ele').innerHTML␣=␣feature.attributes['speed'];
      if␣(tag␣==␣'speed')␣{
      alert(feature.attributes[tag]);
      }
      
      }
      }
      }
      
      //-----------------------------------------------------------------
      //	Naechstliegende␣Komponente␣des␣Features
      //-----------------------------------------------------------------
      
      if␣(nearestComponent)␣{
      
      text␣+=␣'<hr␣/>Lat/Lng:␣'+(pos.lat<0?'S':'N')+Math.abs(pos.lat)+'␣'+(pos.lon<0?'W':'E')+Math.abs(pos.lon)+'<br␣/>';
      
      for␣(var␣tag␣in␣nearestComponent.attributes)␣{
      text␣+=␣tag+':␣'+nearestComponent.attributes[tag]+'<br␣/>\n';
      if␣(tag␣==␣'speed')␣{
      document.getElementById('ele').innerHTML␣=␣nearestComponent.attributes[tag];
      
      }
      }
      }
      
      //-----------------------------------------------------------------
      //	Schliesse␣Popup-<div>
      //-----------------------------------------------------------------
      
      text␣+=␣'<'+'/div>';
      
      //-----------------------------------------------------------------
      //	Erzeuge␣Popup
      //-----------------------------------------------------------------
      
      feature.popup␣=␣new␣OpenLayers.Popup.FramedCloud("gpx",
      hotspot,
      null,
      text,
      null,
      true,
      function()␣{␣selcontrol.unselectAll();␣}
      );
      
      //-----------------------------------------------------------------
      //	Zeige␣Popup
      //-----------------------------------------------------------------
      
      map.addPopup(feature.popup);
      }
      
      //-----------------------------------------------------------------
      //	Zerstoere␣Popup
      //-----------------------------------------------------------------
      
      function␣destroyPopup(feature)␣{
      
      feature.popup.destroy();
      feature.popup␣=␣null;
      }
      
      //-----------------------------------------------------------------
      //	automatisches␣Anlegen␣der␣Controls␣fuer␣die␣Tracks
      //-----------------------------------------------------------------
      
      var␣selcontrol␣=␣new␣OpenLayers.Control.SelectFeature([track],␣{
      
      onSelect:␣createPopup,
      onUnselect:␣destroyPopup,
      lastXy:␣null,
      storePosition:␣function␣(evt)␣{␣this.lastXy=evt.xy;␣}
      });
      
      //-----------------------------------------------------------------
      //	([url]http://wiki.openstreetmap.org/wiki/User:MHohmann[/url])
      //-----------------------------------------------------------------
      
      map.addControl(selcontrol);
      
      //-----------------------------------------------------------------
      //	Aktuelle␣Position
      //-----------------------------------------------------------------
      
      map.events.register('mousemove',selcontrol,selcontrol.storePosition);
      
      //-----------------------------------------------------------------
      //	Aktivieren
      //-----------------------------------------------------------------
      
      selcontrol.activate();
      };
      </script>
      
      <style␣type="text/css">
      .olControlLoadStatus␣{
      left:␣50px;
      top:␣10px;
      }
      </style>
      </head>
      
      <body␣style="margin:␣0">
      
      <div␣style="float:right"><a␣href="http://www.netzwolf.info/kartografie/openlayers/">zur␣&Uuml;bersicht</a></div>
      <h1>Trackdecoder</h1>
      
      <div␣id="map"␣style="background:␣gray;␣width:␣100%;␣height:␣75%;"></div>
      
      <p>
      Klick␣auf␣Track␣zeigt␣im␣Popup␣Detail-Informationen.
      </p>
      
      <p>
      Erkl&auml;rung␣im␣Quelltext␣der␣Seite.
      </p>
      
      <div␣id=ele>
      </div>
      
      </body>
      </html>
      

    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 22.02.2013 00:51 · [flux]

      Nahmd,

      Ghostrider82 wrote:

      Ich versuche gerade krampfhaft, dein GPX Beispiel nachzuvollziehen (http://www.netzwolf.info/kartografie/op … tracks.htm)

      Klappt, unterbringen von zusätzlichen Werte in der GPX Datei sowie Zugriff auf den entsprechenden Wert via feature.attributes['xyz'] klappt auch. Bis dahin schon einmal super.

      Sehr schön.

      In deinem JSON Beispiel wird beim Verschieben bzw. Ändern des Zooms wie gewünscht ein neuer Request erzeugt.

      Beim GPX Beispiel funktioniert dies jedoch nicht. Ist das grundsätzlich so vorgesehen?

      Das hat nicht direkt etwas mit Json/Gpx zu tun, sondern ich hab einfach keine Serverseitige Unterstützung dafür, BBOX-Ausschnitte aus GPXen zu liefern.

      Liegt das am strategies: [new OpenLayers.Strategy.Fixed()] anstelle strategies: [new OpenLayers.Strategy.BBOX({resFactor: 1.0 })]?

      Ja.

      “Strategy.Fixed” (ein toller Name für eine Banalität) holt die angegebene URL genau einmal ab und ist danach zufrieden. Der Server braucht nur zur URL die Daten rauszurücken und gut ist. Keine Intelligenz gefordert.

      Denn tausche ich Fixed() gegen BBox(..) bleibt die Karte dunkel (Scriptfehler bekomme ich jedoch keine.

      Die Strategie Bbox fragt beim Start und später bei (fast) jedem Zoom/Pan die Daten neu ab. Dabei hängt sie an die URL einen Parameter “bbox=W,S,E;N” an. Ein Script/Programm/Servlet auf dem Server soll dann die Daten bereitstellen, die in der angegebenen BBOX liegen.

      Der Grund für die dunkle Karte ist der Münchhausen-Effekt. Jedenfalls habe ich den so getauft, nachdem ich mehrmals darauf reingefallen bin:

      Damit die Karte dargestellt werden kann, braucht es Koordinaten und eine Zoomstufe. Solange die nicht angegeben werden, gibt es auch keine Karte. Und solange keine Karte dargestellt wird und es damit keine aktuelle BBOX gibt, holt die BBOX-Strategie auch nichts ab (Du kannst ins Server-Log gucken – da ist keine Anfrage).

      Die Fixed-Strategie dagegen interessiert sich überhaupt nicht für die Karte und ruft stupide nach der Initialisierung die URL ab.

      Im GPX-Beispiel (Fixed) habe ich die Zeile

      track.events.register("loadend",track,track.zoomMapToMyBounds);
      

      Übersetzt: ruf nach dem Laden des GPX die zoomMapToMyBounds-Methode auf. Die holt sich die Ausmaße des geladenen GPX und zoomt/pant die Karte so, dass das GPX optimal passt.

      Der Ablauf also:

      → Strategy.Fixed ruft GPX ab (bedingungslos)
      → Map wird auf Bbox des Gpx dimensioniert.
      → Map wird gezeichnet.
      🙂

      Ablauf bei Strategy.BBOX:

      → Karte hat keine Größe
      → Ohne Kartengröße ruft Strategy.BBOX die URL nicht ab.
      → Ohne geladenes GPX wird zoomMapToMyBounds nicht aufgerufen
      → ohne zoomMapToMyBounds bekommt die Karte keine Größe.
      → wiederhole ad infinitum
      🙁

      Da versucht sich jemand an den eigenen Haaren aus dem Sumpf zu ziehen. 😛

      Einfache Lösung: wenn Du die Strategy.BBOX verwendest, musst Du der Karte eine Größe geben. Ist wenn es einmal weiß ja auch vollkommen klar, dass die Kartengröße nicht aus den geladenen Daten bestimmt werden kann, wenn die geladenen Daten von der Kartengröße abhängen.

      In meinem Strategy.BBOX-Beispiel findest Du am Ende des JS:

      if␣(!map.getCenter())␣{
      map.zoomToExtent(
      new␣OpenLayers.Bounds(9.98,␣53.47,␣14.49,␣54.33).
      transform(map.displayProjection,␣map.getProjectionObject()));
      }
      

      Das “map.zoomToExtent” sorgt dafür, dass der angegebene Bereich möglichst groß zentriert dargestellt wird. Das “if (!map.getCenter()) {” drum herum unterdrückt die Positionierung, wenn die Seite über einen Permalink aufgerufen wurde.

      Ich hoffe, Du kommst damit weiter.

      Gruß Wolf


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Ghostrider82 (Gast) · 25.02.2013 20:11 · [flux]

      Und auch an dieser Stelle wieder ein großes Dankeschön.

      Nun klappt es nahezu perfekt.

      Darf ich dich nach deinem "Algorithmus" fragen, mit dem du die Daten beim Generieren "generalisierst"?

      Ich mache das nun testweise, indem ich den Timestamp (zu dem die Koordinate gespeichert wurde) per Modulo herausfiltere. Das hat aber zur Folge, dass bei jedem Zoomwechsel andere Linestrings erzeugt werden, was ein wenig unbefriedigend auf der Karte aussieht, quasi wie ein Netz, dass immer wieder anders aufgebaut wird.


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 25.02.2013 20:43 · [flux]

      Nahmd,

      Ghostrider82 wrote:

      Darf ich dich nach deinem "Algorithmus" fragen, mit dem du die Daten beim Generieren "generalisierst"?

      Konzeptionell läuft es so ab (die Implementierung fasst die Schritte natürlich zusammen):

      Der Client übergibt die bbox und die mindist.

      Im ersten Schritt werfe ich alle Punkte außerhalb der Bbox weg bis auf die, die direkte Nachbarn eines Punktes innerhalb der Bbox sind. Dabei kann die Linie in mehrere Teile zerfallen.

      Der Hanseweg z.B. hat Schlenker nach Norden, wenn ich mich darunter positioniere, läuft der Weg oben aus der Bbox raus und kommt wieder rein.

      Von jeder Teillline nehme ich den Startknoten und den Endknoten *immer* in das Ergebnis auf.

      Jetzt beginne ich am Startknoten und suche den ersten Nachfolgeknoten, der *mindestens* die "mindist" entfernt ist.

      Ich zähle also nicht Knoten ab, sondern beziehe auch den Abstand zwischen den Knoten ein. Das Segment zwischen zwei Knoten kann ein langer gerader Weg sein (mal nach Stellweg im Siebengebirge suchen), oder ein Stück einer Serpentinenkurve mit Dezimeterlänge.

      Den ersten Knoten im Abstand mindist nehme ich in die Ergebnisliste auf und suche von da aus wieder den nächsten Knoten mit Mindestabstand.

      Alles sehr einfach.

      .oO( Mist! Jetzt kann ich es nicht mehr patentieren lassen. 😉 )

      Das hat aber zur Folge, dass bei jedem Zoomwechsel andere Linestrings erzeugt werden, was ein wenig unbefriedigend auf der Karte aussieht, quasi wie ein Netz, dass immer wieder anders aufgebaut wird.

      Bei mir werden bereits bei einem Pan anderes Stützpunkte gewählt. Außerdem schaue ich mir bei jeder Auflösung *alle* Knoten an. Das geht bei den 9000 der Hanseweg noch (ist aber grob ungehörig), die Chinesische Mauer jedoch kann ich so nicht mehr handhaben.

      Die Lösung dafür ist auf Papier schon fertig und harrt nur noch des eingetippert werdens.

      Gruß Wolf


    • Re: POIs/Polylines nur je Kartenausschnitt laden · mmd (Gast) · 27.02.2013 21:01 · [flux]

      .


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Netzwolf (Gast) · 28.02.2013 00:21 · [flux]

      Nahmd,

      mmd wrote:

      Postgis und openlayers verwenden dafür soweit ich das gesehen habe Douglas peucker
      Zum ausprobieren:
      http://openlayers.org/dev/examples/simp … tring.html

      Der Vorteil des Greedy-Algorithmus besteht darin, dass der nicht nur dieses Probleme löst, sondern auch fast alle anderen. 🙂
      Deshalb muss ich nicht so viele Algorithmen kennen. 😎

      Gruß Wolf


    • Re: POIs/Polylines nur je Kartenausschnitt laden · Ghostrider82 (Gast) · 13.06.2013 20:27 · [flux]

      @Netzwolf

      Ich habe mich in den vergangenen Tagen wieder ein wenig ausführlicher mit der Thematik auseinander gesetzt.
      Würdest du das CGI Script aus deinem Beitrag #3 zur Verfügung stellen?
      Ich würde das dann in PHP übersetzen. Natürlich unter den von dir genannten Kriterien ;-)