轨迹中的驻留点计算
最近根據業(yè)務需要,編寫了一個小的算法,用于從設備的軌跡中提取出設備的駐留點。其中關于時間的驗證,使用了上一篇文章中的時間工具js,設備的軌跡是用一個點數組來表示的,駐留點也是一個點的數組。
function checkDistance(pointArrayBeforenowPoint,nowPoint,stayDistance){var pf=pointArrayBeforenowPoint;if(pf.length==1){return 1;//代表此點是第二個點,可以直接返回ture}else{for(var i=0;i<pf.length;i++){var distance=getDistanceBetween(pf[i],nowPoint);if(distance<5){//誤差距離,在此處默認為5m,也就說說,5米范圍內的點可以作為另外一個點的誤差點,而不需要額外計算。return 2;//代表此點可忽略}else{if(distance<(stayDistance*2)){continue;}else{return 0;//代表此點不符合距離要求,駐留點序列斷裂}}}return 1;//符合要求的主流點被加入。}}function checkTime(stayPointSet,stayTime){var lastIndex=stayPointSet.length-1;var startPointSetTime=getDateFromformatString(stayPointSet[0].createtime,"YYYY-MM-DD hh:mm:ss.S");var endPointSetTime=getDateFromformatString(stayPointSet[lastIndex].createtime,"YYYY-MM-DD hh:mm:ss.S");var howLong = endPointSetTime.minusDate(startPointSetTime);if(howLong>=stayTime){return true;}else{return false;}}function getStayPoints(stayPointSetsArray){var stayPoints = new Array();for(var i=0;i<stayPointSetsArray.length;i++){var stayPointsInfo=new Array();var sumX=0,sumY=0,averageX=0,averageY=0,n=0;var setLength=stayPointSetsArray[i].length;for(var j=0;j<setLength;j++){if(j==0){stayPointsInfo.startTime=stayPointSetsArray[i][j].createtime;}else if(j==setLength-1){stayPointsInfo.endTime=stayPointSetsArray[i][j].createtime;}sumX+=stayPointSetsArray[i][j].x;sumY+=stayPointSetsArray[i][j].y;n+=1;}averageX=sumX/n;averageY=sumY/n;stayPointsInfo.point=new EzCoord(averageX,averageY);stayPoints.push(stayPointsInfo);}return stayPoints;}function getDistanceBetween(point1,point2){var pos1 = new EzCoord(point1.x,point1.y);var pos2 = new EzCoord(point2.x,point2.y);return pos1.distanceTo(pos2);}/*** 創(chuàng)建定位點序列類*/function PositionList(PositionList){this.positionList=PositionList;}/*** 根據傳入的駐留時間和駐留距離,計算出整個軌跡序列點鐘的所有駐留點。返回一個EzCoord型數據組成的數組。* @param stayTime 最短駐留時間,低于這個時間的駐留,不被定義為駐留點,默認30min* @param stayDistance 駐留距離,駐留期間,所有定位點的位置都分布在一個以“駐留距離”為半徑的圓內部(在圓弧上的點不在圓的內部)。* 默認50m(不包括50m,半徑50m,直徑則為100m)。* @returns stayPoints array* @author yin_zhida*/PositionList.prototype.getStayPoints=function(stayTime,stayDistance){if(stayTime==undefined||stayTime==null){stayTime=1000*60*30;//單位毫秒}if(stayDistance==undefined||stayDistance==null){stayDistance=50;//單位M}var _positionArray=this.positionList;var stayPointSetsArray=new Array();for(var i=0;i<_positionArray.length;i++){var checkPointSet=new Array();var stayPointSet=new Array();var nowPoint=_positionArray[i];var nextPoint=null;var nextDistance=null;if(i<(_positionArray.length-1)){var nexti=i+1;nextPoint=_positionArray[nexti];}if(nextPoint!=null){nextDistance=getDistanceBetween(nowPoint,nextPoint);}if(nextDistance!=null&&nextDistance<(stayDistance*2)){stayPointSet.push(_positionArray[i]);checkPointSet.push(_positionArray[i]);var nextI=i+1;for(var j=nextI;j<_positionArray.length;j++){var jPoint=_positionArray[j];var jprePoint=null;var jpreDistance=null;var prej=j-1;jprePoint=_positionArray[prej];jpreDistance=getDistanceBetween(jPoint,jprePoint);if(jpreDistance!=null&&jpreDistance<(stayDistance*2)){var chk = checkDistance(checkPointSet,jPoint,stayDistance);if(chk==0){i=j-1;break;}else if(chk==1){stayPointSet.push(_positionArray[j]);checkPointSet.push(_positionArray[j]);}else if(chk==2){stayPointSet.push(_positionArray[j]);}}else{i=j-1;break;}}}if(stayPointSet.length>1&&checkTime(stayPointSet,stayTime)){stayPointSetsArray.push(stayPointSet);}}return getStayPoints(stayPointSetsArray);}; 代碼相關的注釋寫的很清楚,其中 ?new EzCoord(x,y)是筆者所使用的地圖接口創(chuàng)建“地圖點”類的方法,通過該類自帶的distanceTo方法計算兩點之間的距離。
該算法需要傳遞兩個參數,一個是駐留距離,一個是駐留的最短時間,也就是說,一個設備在最短駐留時間內移動的距離小于駐留距離那么這個設備在此期間就被定義為駐留點了。
最后算法中還內定了一個誤差的默認值(5),代表了如果一個設備的定位點有5m的誤差,在5m內的移動將被忽略,這樣做將某臺設備在一段時間內沒有移動的情況進行了簡單的過濾處理,很大程度的提升了算法的效率。
代碼如有需要提升的地方,還望大家指正,或者您有什么好的提議也可以拿來與我討論。
原創(chuàng)文章,轉載請說明出處。
總結
- 上一篇: 魔兽世界钓鱼大赛冠军心得
- 下一篇: Iphone, Ipad, Iwatch