使用指南

本文介绍Ganos时空引擎功能的时空轨迹使用示例。

Java API(兼容GeoMesa的时空专用接口)

以轨迹分段线模型为例。

建表

  1. 定义轨迹点模型SimpleFeatureType。

String pointSpec = "id:String,dtg:Date,*geom:Point:srid=4326";
SimpleFeatureType pointSFT = SimpleFeatureTypes.createType("point", pointSpec);

由于每个轨迹点也是具有属性的时空对象,在定义分段模型前,需要先定义点模型。

2. 创建轨迹线模型TrajectoryFeatureType。

TrajectoryBuilder trajBuilder = new TrajectoryBuilder(“trajectory", pointSFT, "dtg", "id", true);
TrajectoryFeatureType trajFeatureType = trajBuilder.getTrajFeatureType();

使用Lindorm Ganos提供的帮助类TrajectoryBuilder,基于点模型创建轨迹线模型。创建TrajectoryBuilder时,需要指明pointSFT的时间和ID字段。

TrajectoryFeatureType有默认属性字段,参见基本概念(轨迹存储模型-线/分段线模型各属性字段定义)。默认的基本字段必须包括且不能修改,可以使用TrajectoryBuilder的addTrajProperties方法,增加新的轨迹属性字段。

TrajectoryBuilder trajBuilder = new TrajectoryBuilder(“trajectory", pointSFT, "dtg", "id", true);
trajBuilder.addTrajProperties("speed:Double,traj_end_time:Date");
TrajectoryFeatureType trajFeatureType = trajBuilder.getTrajFeatureType();

3. 指定创建二级索引的必要信息。

trajFeatureType.getUserData().put("geomesa.secondary.enabled","true");
trajFeatureType.getUserData().put("geomesa.primary.index","id");
trajFeatureType.getUserData().put("geomesa.indices.enabled","id,xz2t");

通过设置TrajectoryFeatureType的userData指定创建二级索引的必要信息。本例指定ID为主表索引,创建针对时空属性的xz2t二级索引。

4. 创建表。

ds.createSchema(trajFeatureType);

调用Lindorm Ganos兼容的Geotools API:DataStore.createSchema创建表(DataStore获取方法请参见快速入门)。此时主表和二级索引表都已创建,二级索引表由Lindorm封装维护,对用户不可见。

写入轨迹数据

1. 创建轨迹点。

public SimpleFeature createFeature(SimpleFeatureType sft, String id, Object... values){
  SimpleFeatureBuilder sfBuilder = new SimpleFeatureBuilder(sft);
  SimpleFeature simpleFeature = sfBuilder.buildFeature(id,values);
  return simpleFeature;
}

List<SimpleFeature> points = new ArrayList<>();
for(String pointData: rawData) {
    // parse id and point values from pointData
    String pointID = ...;
    Object[] values = ...;
    
    points.add(createFeature(pointSFT, pointID, values);
}

根据前面的点模型定义,从原始数据解析轨迹点信息,创建轨迹点对象。

2. 定义轨迹分段策略。

SplitConfigs splitConfigs = new SplitConfigs(SplitConfigs.BY_COUNT(), new Object[]{50});

本例采用每段50个点划分一段的分段策略。

3. 创建轨迹段。

String objectID = "001";
List<SimpleFeature> trajFeatures = trajBuilder.createTrajSegments(objectID, features, splitConfigs); 

指定objectID,使用TrajectoryBuilder.createTrajSegments方法,得到基于轨迹点List切分后的轨迹段。

注意如果前面使用addTrajProperties增加了轨迹段属性,需要在createTrajSegments时传入增加的轨迹段属性值。

Object[] extraTrajProperties = new Object[]{speed, trajEndTime};
List<SimpleFeature> trajFeatures = trajBuilder.createTrajSegments(objectID, features, splitConfigs, extraTrajProperties); 

4. 批量写入轨迹段。

SimpleFeatureStore featureStore = (SimpleFeatureStore) ds.getFeatureSource(trajFeatureType.getTypeName());
featureStore.addFeatures(new ListFeatureCollection(trajFeatureType, trajFeatures));

调用Lindorm Ganos兼容的GeoTools API:SimpleFeatureStore.addFeatures 批量写入轨迹段。

查询

Lindorm Ganos兼容GeoMesa支持的CQL语法,可参考查询时空对象。轨迹模型目前支持的查询有:

查询类型

示例

ID+时间查询

object_id in ('001') and seg_start_time > 1549522511

属性查询

speed > 2.0 (点模型则查询点属性,线模型则只能查询整条轨迹/轨迹段的属性)

空间范围查询

INTERSECTS (geom, POLYGON ( (-78 26,-73 26,-73 31,-78 31,-78 26) ) )

时空范围查询

INTERSECTS (geom, POLYGON ((-78 26,-73 26,-73 31,-78 31,-78 26))) AND traj_start_time >= 1549510271 AND traj_start_time <= 154958204

查询步骤示例。

//创建查询语句
String ecqlPredicate = “INTERSECTS(geom, POLYGON ((-78 26,-73 26,-73 31,-78 31,-78 26))) AND traj_start_time >= 1549510271 AND traj_start_time <= 1549582040”;

// 构建Query
String schemaName = "trajectory"; // named when creating table
Query query = new Query("trajectory", ECQL.toFilter(ecqlPredicate));

//获取查询结果
if(!getCompleteTrajectory) { // 如果只需要返回满足条件的轨迹段
    SimpleFeatureCollection featureCollection = ((LindormDataStore)ds).getFeatureSource(“trajectory").getFeatures(query);
    SimpleFeatureIterator iterator = result.features();
    while (iterator.hasNext()) {
      iterator.next();
    }
} else { // 如果需要获取完整轨迹
    List<TrajectoryFeature> trajectories = ((LindormDataStore)ds).getFeatureSource(“trajectory").getWholeTrajectoies(query);
}