本文介绍Ganos时空引擎功能的时空轨迹使用示例。
Java API(兼容GeoMesa的时空专用接口)
以轨迹分段线模型为例。
建表
定义轨迹点模型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+时间查询 |
|
属性查询 |
|
空间范围查询 |
|
时空范围查询 |
|
查询步骤示例。
//创建查询语句
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);
}