2013-10-29 4 views
0

GPS를 통해 대략 100 대의 차량의 실시간 위치를 추적하는 코드를 작성하려고합니다. 마지막으로 X/Y 지점과 현재 지점 사이의 보간 경로를 따라 위치를 설정하여 각 차량에 대한 Google지도 마커를 부드럽게 "애니메이트"하고 싶습니다. URL을 호출하여 setInterval 호출을 통해 매 15 초마다 모든 현재 차량 위치가있는 JSON 객체를 가져옵니다. 그 안에 JSON 객체의 각 차량을 반복하고 차량 위치를 설정합니다. 나는 모션을 애니메이트하는 함수를 가지고 있지만 그것은 단지 하나의 차량에만 안정적으로 작동한다. 중첩 된 setInterval 함수가 for 루프의 다음 단계 전에 완료되지 않을 것이기 때문에 나는 믿는다. 내부 setInterval 함수를 완료하기 위해 실행해야한다. 내 for 루프에서 다음 "i"전에? 대신 하나를 실행 여러 setInterval()를 실행하고, 그 하나 개의 함수 호출 내에서 이상 모든 차량을 반복하는 데 노력자바 스크립트 여러 비동기 setInterval

setInterval(function() { 
    $(document).ready(function() { 
     $.getJSON("http://localhost:8080/portal/frfeed/query/tampa_sw/paraVehicle?r=" + Math.random(),function(vehicles){ 
      $.each(vehicles, function(index, d){ 

      if(d.heading>=0 && d.heading<22.5) direction="NORTH"; 
      else if(d.heading>=22.5 && d.heading<67.5) direction="NORTHEAST"; 
      else if(d.heading>=67.5 && d.heading<112.5) direction="EAST"; 
      else if(d.heading>=112.5 && d.heading<157.5) direction="SOUTHEAST"; 
      else if(d.heading>=157.5 && d.heading<202.5) direction="SOUTH"; 
      else if(d.heading>=202.5 && d.heading<247.5) direction="SOUTHWEST"; 
      else if(d.heading>=247.5 && d.heading<292.5) direction="WEST"; 
      else if(d.heading>=292.5 && d.heading<338) direction="NORTHWEST"; 
      else direction="NORTH"; 
      vehicle = ""; 

       for (var i=0; i<vMarkers.length; i++) { 
        if(vMarkers[i][0] === d.internalVehicleId) { 
         var path; 
         var latlng = new google.maps.LatLng(d.latitude,d.longitude); 
         vMarkers[i][2] = vMarkers[i][1].getPosition().lat(); 
         vMarkers[i][3] = vMarkers[i][1].getPosition().lng(); 
         vMarkers[i][4] = latlng; 
         vMarkers[i][1].setTitle('Vehicle: ' + d.internalVehicleId + '\r\n' + 'Last Update: ' + d.time + '\r\n' + 'Traveling: ' + direction + ' @ ' + d.speed + ' mph'); 
         path = vPolys[i][1].getPath(); 
         path.push(latlng); 
         vPolys[i][1].setPath(path); 
         vehicle = vMarkers[i][0]; 

         var lat = vMarkers[i][2]; 
         var lng = vMarkers[i][3]; 
         var latlngTo = vMarkers[i][4]; 
         var latLngFrom = new google.maps.LatLng(lat,lng);        
         j = 0; 
// function below only works correctly if filtered for one vehicle as below, otherwise, all 
// markers randomly move and don't stop due to the setInterval being called inside the for loop 

         if (distance(latlngTo.lat(), latlngTo.lng(),latLngFrom.lat(), latLngFrom.lng()) > 20 && vMarkers[i][0] == "1329") { 
          iv = window.setInterval(function() { 
           j++; 
           var pos = mercatorInterpolate(map, latLngFrom, latlngTo, j/50); 
           vMarkers[i][1].setPosition(pos); 
           if (j >= 50) { 
            window.clearInterval(iv); 
             } 
            }, 20); 
           } 
           else { 
            vMarkers[i][1].setPosition(latlngTo); 
           }; 

           break; 
          } 
         } 
         if(vehicle == "") { 
          color = get_random_color(); 
          marker = new StyledMarker({ 
           styleIcon:new StyledIcon(StyledIconTypes.BUBBLE,{color:color, fore: "ffffff",text: d.internalVehicleId}), 
           position: new google.maps.LatLng(d.latitude,d.longitude), 
           title: 'Vehicle: ' + d.internalVehicleId + '\r\n' + 'Last Update: ' + d.time + '\r\n' + 'Traveling: ' + direction + ' @ ' + d.speed + ' mph', 
           map: map 
          }); 
          var polyOptions = { 
           strokeColor: color, 
           strokeOpacity: 1.0, 
           map: map, 
           strokeWeight: 3 
          };         
          poly = new google.maps.Polyline(polyOptions); 
          var latlng = new google.maps.LatLng(d.latitude,d.longitude); 
          vMarkers.push([d.internalVehicleId, marker, d.latitude, d.longitude, latlng]); 
          var path = poly.getPath(); 
          path.push(latlng); 
          poly.setPath(path); 
          vPolys.push([d.internalVehicleId, poly]) 
          vehicle = ""; 
         } 
        });//$.each(vehicles, function(index, d){ 

        function mercatorInterpolate(map, latLngFrom, latLngTo, fraction) { 
         // Get projected points 
         var projection = map.getProjection(); 
         var pointFrom = projection.fromLatLngToPoint(latLngFrom); 
         var pointTo = projection.fromLatLngToPoint(latLngTo); 
         // Adjust for lines that cross the 180 meridian 
         if (Math.abs(pointTo.x - pointFrom.x) > 128) { 
          if (pointTo.x > pointFrom.x) 
           pointTo.x -= 256; 
          else 
           pointTo.x += 256; 
         } 
         // Calculate point between 
         var x = pointFrom.x + (pointTo.x - pointFrom.x) * fraction; 
         var y = pointFrom.y + (pointTo.y - pointFrom.y) * fraction; 
         var pointBetween = new google.maps.Point(x, y); 
         // Project back to lat/lng 
         var latLngBetween = projection.fromPointToLatLng(pointBetween); 
         return latLngBetween; 
        } 

        function distance(lat1,lon1,lat2,lon2) { 
         var R = 6371; 
         var dLat = (lat2-lat1) * Math.PI/180; 
         var dLon = (lon2-lon1) * Math.PI/180; 
         var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
          Math.cos(lat1 * Math.PI/180) * Math.cos(lat2 * Math.PI/180) * 
          Math.sin(dLon/2) * Math.sin(dLon/2); 
         var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
         var d = R * c; 
         return Math.abs(d*1000); 
        } 
       }); //$.getJSON(...., function(vehicles) { 
      }); //$(document).ready(function() { 
     }, 16000); // setInterval(function(){ 

답변

0

. 예를 들어

:가 호출 될 빈도, 단지의 최소 간격을 보장하지 않습니다

iv = setInterval(function() { 
    for (int i=0; i<vehicleArray.length;i++) { 
    // Do stuff for each vehicle. 
    } 
}, 40); 

setInterval()있다. 이것은 우연한 추적으로 이어질 수 있습니다. setInterval() 함수를 입력 할 때마다 시계를 읽고이를 기반으로 새로운 위치를 계산하여이를 피하십시오.

코드는 초당 50 프레임을 달성하려고 시도하고 있으며 이는 낙관적 인 것으로 입증 될 수 있습니다. 반으로 부드럽게 효과를 낼 수 있습니다. 즉 40ms 간격으로 전송된다.

1

아니요, setInterval은 비동기입니다. 당신은 asycronous 코드로 작동하는 방식으로 프로그램을 작성해야합니다.

애니메이션의 경우 부드러운 결과를 얻으려면 실제로 requestAnimationFrame을 사용해야합니다.

나는 15 초마다 자동차의 배열을 밀고 프레임 배열을 만들 것이다. 를 저장하는 각 자동차는 그때 requestAnimationFrame를 사용하고 당신은 내가 무슨 짓을했는지 다음이 훨씬 더 최적화 할 수

var currentFrame = 0; 
var startTime = 0; 

function update(){ 
    var currentTime = newDate(); 
    startTime || startTime = currentTime; 

    var elaspedTime = Math.floor(currentTime.getTime() - startTime.getTime())/1000; 

    // increment the current frame if 15 seconds have elapsed 
    elaspedTime%15 === 0 && currentFrame++; 

    // Get the current frame 
    var frame = frames[currentFrame], 
     nextFrame = frames[++currentFrame]; 

    // Loop over each car in the frame 
    for(var i = 0; i < frame.length; i++){ 
    // Calculate the difference in location 
    var xDiff = nextFrame[i].x - frame[i].x; 
    var yDiff = nextFrame[i].y - frame[i].y; 

    // interpolate the current position of the cars 
    var xPos = xDiff/elaspedTime%15; 
    var yPos = yDiff/elaspedTime%15; 

    // do some work here to set the position of the cars 
    } 

    requestAnimationFrame(update); 
} 

requestAnimationFrame(update); 

각 차량의 현재 위치를 보간 할 위치

var frames = [[{x: 10, y:2},{x: 5, y:6}], [{x: 12, y:4},{x: 7, y:8}]] 

, 그러나 이것은 내가 얼마나입니다 접근한다.

관련 문제