轨迹数据管理与分析

轨迹分段

2022-04-07  本文已影响0人  大鱼馆长

1. 定义

轨迹分段:对去噪后的轨迹,根据驻留点信息或者相邻GPS点之间的时间间隔,将其划分成多个连续的GPS子序列,这些子序列便是分段后的子轨迹。

图1 轨迹分段示意图

轨迹去噪驻留点检测请参考我的轨迹相关专栏文章。

2. 算法概述

2.1 基于驻留点的轨迹分段

利用驻留点检测技术,检测出轨迹中的所有驻留点,然后从轨迹中剔除驻留点, 得到多个轨迹。

2.2 基于时间间隔的轨迹分段

如果轨迹中两个相邻GPS点的时间间隔大于指定的阈值t,则将轨迹从这两个点之间截断,得到两条子轨迹。

3. 代码实现

完整的Scala代码实现请参考我的GitHub

3.1 接口定义
trait AbstractTrajectorySegment {
  /**
   * Segment trajectory
   *
   * @param trajectory raw long trajectory
   * @return segmented sub-trajectories
   */
  def segment(trajectory: Trajectory): Array[Trajectory]
}
3.2 基于驻留点的轨迹分段
class StayPointBasedSegment(detector: AbstractStayPointDetector) extends AbstractTrajectorySegment {
  /**
   * Segment trajectory
   *
   * @param trajectory raw long trajectory
   * @return segmented sub-trajectories
   */
  override def segment(trajectory: Trajectory): Array[Trajectory] = {
    val gpsCoordinates = trajectory.getCoordinatesGPS
    val stayPointBounds = detector.calStayPointBounds(gpsCoordinates)

    var trajStartIndex = 0
    val subTrajectories = new ArrayBuffer[Trajectory]()
    for ((stayPointStartIndex, stayPointEndIndex) <- stayPointBounds) yield {
      if (trajStartIndex < stayPointStartIndex - 1) {
        val subCoordinates = gpsCoordinates.slice(trajStartIndex, stayPointStartIndex)
        subTrajectories += new Trajectory(trajectory.oid, subCoordinates)
      } else {
        //coordinate number is less than 2, can't build a trajectory
      }
      trajStartIndex = stayPointEndIndex + 1
    }

    if (trajStartIndex < gpsCoordinates.length - 1) {
      //don't forget the last sub trajectory
      subTrajectories += new Trajectory(trajectory.oid, gpsCoordinates.slice(trajStartIndex, gpsCoordinates.length))
    }
    subTrajectories.toArray
  }

}
3.3 基于时间间隔的轨迹分段
class TimeIntervalSegment(maxTimeIntervalInSec: Double) extends AbstractTrajectorySegment {
  /**
   * Segment trajectory
   *
   * @param trajectory raw long trajectory
   * @return segmented sub-trajectories
   */
  override def segment(trajectory: Trajectory): Array[Trajectory] = {
    val gpsCoordinates = trajectory.getCoordinatesGPS

    var trajStartIndex = 0
    val subTrajectories = new ArrayBuffer[Trajectory]()
    for (index <- gpsCoordinates.indices.dropRight(1)) {
      val timeInterval = gpsCoordinates(index).time.toInstant.getEpochSecond -
        gpsCoordinates(index + 1).time.toInstant.getEpochSecond
      if (timeInterval > maxTimeIntervalInSec) {
        if (trajStartIndex < index) {
          subTrajectories += new Trajectory(trajectory.oid, gpsCoordinates.slice(trajStartIndex, index + 1))
        } else {
          //coordinate number is less than 2, can't build a trajectory
        }
        trajStartIndex = index + 1
      }
    }

    if (trajStartIndex < gpsCoordinates.length - 1) {
      //don't forget the last sub trajectory
      subTrajectories += new Trajectory(trajectory.oid, gpsCoordinates.slice(trajStartIndex, gpsCoordinates.length))
    }
    subTrajectories.toArray
  }
}

4. 总结

轨迹分段就是将整条轨迹在卡点的地方截断,形成多条子轨迹。卡点可以是轨迹的驻留点,也可以是两个时间间隔很大的GPS点对

上一篇 下一篇

猜你喜欢

热点阅读