GPS Tracker z pliku .GPX

Witam.

Chciałbym zrobić GPS Tracker ktróry pobiera kolejne współrzedne z pliku GPX i wyświetla je na mapie np. w postaci poruszającego się markera. Nie chodzi o to żeby wczytać całość na raz bo to jest już w sieci. Najlepiej gdyby marker wczytywał pierwszy punkt i w czasie kiedy wczytuje drugi znikał z pierwszego położenia. Plik GPX odczytuje przez OpenLayers.Layer.Vector http://dev.openlayers.org/docs/files/OpenLayers/Layer/Vector-js.html. Mam teraz problem z pobraniem stąd kolejnych punktów. Myślałem nad getFeatureBy http://dev.openlayers.org/docs/files/OpenLayers/Layer/Vector-js.html#OpenLayers.Layer.Vector.getFeatureBy ale nie wiem za bardzo jak tego użyć(jakbym nie próbował to nie działa).

Czy to jest dobra metoda? Czy macie inne pomysły?

Mam mały pomysł, lecz nie jestem pewien czy zadziała (nie mam dużego doświadczenia z OL).

  1. Pobierasz cały plik GPX
  2. Parsujesz go na tablice punktów
  3. Pętlą zmieniasz współrzędne markera http://dev.openlayers.org/docs/files/OpenLayers/Feature-js.html

Można jeszcze dodać jakaś interpolacje, aby punkt płynniej się poruszał

Jak wykonać pkt2? W tej chwili mam warstwę z cała trasą. Z programowania jestem słaby więc przydałby się jakiś prosty przykład.

Hmmm… w takim razie jest to spore utrudnienie. Powinieneś poczytać kursy javascript, bo bez tego będzie bardzo ciężko. Mogę napisać mniej-więcej jak ja to widzę.


function downloadGPX(adres){
    //Tutaj kod pobierający dane
    return string;
}

function parseGPX(string){
  //Tutaj parsowanie np. za pomocą jquery
  return tmp_array;
}

var marker;

//Funkcja wywołana np. przyciśnięciem buttona
function showOnMap(){
   points = parseGPX(downloadGPX('twojGPX.gpx'));
   for (var x=0; x<points.length; x++) {
      marker.lonlat=new OpenLayers.LonLat(points[x].lon,points[x].lat);
      sleep(100);
   }
}

function init(){
   //Tutaj ustawiasz swoją mapkę
   //Dodawanie markerów
var markers = new OpenLayers.Layer.Markers( "Markers" );
map.addLayer(markers);

marker=new OpenLayers.Marker(new OpenLayers.LonLat(0,0));
markers.addMarker(marker);
}


Kod napisany na szybko i nie testowany :slight_smile: służy jedynie do pokazania o co mi chodziło.

Ok, dzięki. Zaraz spróbuje coś z tym zrobić :wink:

Nie trzeba aż tak dużo pisać swojego kodu :slight_smile: w zupełności wystarczy parser GPX, który już jest wbudowany w OL. Ja bym to zrobił tak:

  • wczytanie warstwy z linią, dokładnie tak jak to było napisane wcześniej (przez new OpenLayers.Layer.Vector),
  • zadeklarowanie pustej warstwy, na której będziemy wyświetlać punkty:
var markers = new OpenLayers.Layer.Vector("Punkty trasy", {}) // NIE używamy klasy Layer.Markers, bo jest przestarzała
  • następnie pobieramy sobie wierzchołki za pomocą takiej oto funkcji:

var punkty = trasa.features[0].geometry.getVertices() //to jest w przypadku, gdy jest tylko jeden track, jak będzie więcej - trzeba zrobić pętlę,

  • i wyświetlamy na mapie:

for (i=0;i<punkty.length;i++) {
markers.removeAllFeatures();
markers.addFeatures(new OpenLayers.Feature.Vector(punkty[i]),{});
}

Problem w tym, że całość przeleci tak szybko, że animacji nie zdąży się zobaczyć, a funkcji sleep() w javascript… nie ma. Ale gdzieś widziałem, że można takową dorobić.

Domyślałem się, że moje rozwiązanie jest mocno okrężne :stuck_out_tongue:

A masz jakiś pomysł na spowolnienie wykonania? Teraz jest teleportacja :slight_smile:

var i=0;
var intervalVariable=setInterval(function(){
    if (i<punkty.length){
        markers.removeAllFeatures();
        markers.addFeatures(new OpenLayers.Feature.Vector(punkty[i]),{});
        i++;
    }else{
        clearInterval(intervalVariable)
    }
},300);

?

Działa jak marzenie :slight_smile:

hmm, a ja mam problem bo wyskakuje mi błąd:

TypeError: trasa.features[0] is undefined

:confused:

Czy trasa została prawidłowo dodana do mapy? Jeżeli tak:
Po komunikacie o błędzie wnioskuję, że używasz firebuga - może wpisz takie coś w konsoli:

console.log(trasa)

i zobacz, co wypluje. Powinno być:

Object { metadata={...}, options={...}, strategies=[2], more...}

po kliknięciu na “more” będzie można dobrać się do atrybutu “features” i zobaczyć, co się w nim znajduje.

Jest widoczna na mapie jako dodatkowa warstwa.

map.addLayer(trasa);

wywala coś takiego:

ReferenceError: trasa is not defined

więc nie wiem co może być nie tak skoro mam zdefiniowaną tak jak wstawiłem na początku :confused:

Spróbuj wynieść deklarację trasy poza funkcję init(), albo usunąć var na początku. Pierwsze rozwiązanie jest bardziej poprawne, ale może się coś innego posypać :wink:

Zrobiłem tak jak powiedziałeś ale to nie pomogło… To mój cały kod, jak ktoś chciałby rzucić okiem to zapraszam i byłbym wdzięczny za pomoc :wink:

Firebug nadal wyrzuca:

TypeError: trasa.features[0] is undefined
var punkty = trasa.features[0].geometry.getVertices()[0]
<!DOCTYPE HTML>
<html>
  <head>
    <title>OpenLayers Demo</title>
    <style type="text/css">
      html, body, #basicMap {
          width: 100%;
          height: 100%;
          margin: 0;
      }
    </style>
    <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
    <script>
	
	
	//Warstwa z GPX Track
	var trasa = new OpenLayers.Layer.Vector("GPX Track", {
		strategies: [new OpenLayers.Strategy.Fixed()],
		protocol: new OpenLayers.Protocol.HTTP({
			url: "warkie.gpx",
			format: new OpenLayers.Format.GPX()
			}),
		style: {strokeColor: "red", strokeWidth: 5, strokeOpacity: 0.5, strokeDashstyle: 'dot',},
		projection: new OpenLayers.Projection("EPSG:4326")
			
			
		})
	
	
      function init() {
	  	var options = {
		units:'m',
		minResolution: 'auto',
		maxResolution: 'auto',
		controls: [
		new OpenLayers.Control.Navigation(),
          // elementy nawigacyjne w lewym górnym rogu,
          // new OpenLayers.Control.PanZoom(),
          // elementy nawigacyjne w lewym górnym rogu i pionowy suwak zmiany powiększenia,
          new OpenLayers.Control.PanZoomBar(),
          // umożliwia  przewijanie i powiększanie mapy za pomocą klawiatury
          new OpenLayers.Control.KeyboardDefaults(),
          // zminimalizowane okno przełącznika warstw;
          // niebieski przycisk (+) w prawym górnym rogu
          layerSwitcher = new OpenLayers.Control.LayerSwitcher(),  
          // zminimalizowane okno mini-mapy, która umożliwia szybką nawigację;
          // niebieski przycisk (+) w dolnym prawym rogu 
          new OpenLayers.Control.OverviewMap(), 
          // bezpośredni odnośnik do mapy startowej: link w prawym dolnym rogu
          new OpenLayers.Control.Permalink('permalink'),
          // aktualne współrzędne geograficzne punktu pod kursorem myszy;
          // widoczny w prawym dolnym rogu
          new OpenLayers.Control.MousePosition(),          
          // liniowy wskaźnik bieżącego powiększenia mapy; w lewym dolnym rogu mapy, 
          new OpenLayers.Control.ScaleLine()
		]
		};
	  
        map = new OpenLayers.Map("basicMap",options);
        var mapnik         = new OpenLayers.Layer.OSM();
        var fromProjection = new OpenLayers.Projection("EPSG:4326");   // Transform from WGS 1984
        var toProjection   = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection
        var position       = new OpenLayers.LonLat(21.020,52.259).transform( fromProjection, toProjection);
        var zoom           = 10; 
		
		// Dodawanie warstw
        map.addLayer(mapnik);
        map.setCenter(position, zoom );
		map.addLayer(trasa);
		
		
		var markers = new OpenLayers.Layer.Vector("Punkty trasy", {})
		var punkty = trasa.features[0].geometry.getVertices()[0]
		for (i=0;i<punkty.length;i++) {
		markers.removeAllFeatures();
		markers.addFeatures(new OpenLayers.Feature.Vector(punkty[i]),{});
		}
		
		
		var i=0;
		var intervalVariable=setInterval(function(){
		if (i<punkty.length){
        markers.removeAllFeatures();
        markers.addFeatures(new OpenLayers.Feature.Vector(punkty[i]),{});
        i++;
		}else{
        clearInterval(intervalVariable)
		}
		},300);
		
		
      }
    </script>
  </head>
  <body onload="init();">
    <div id="basicMap"></div>
  </body>
</html>