类 LinearReferencing
- java.lang.Object
-
- com.supermap.analyst.spatialanalyst.LinearReferencing
-
public class LinearReferencing extends Object
线性参考类。该类提供用于动态分段的生成路由数据集、校准路由数据集、创建事件表、创建空间数据及事件表的叠加与融合等功能的实现。-
线性参考和动态分段
要理解为什么使用动态分段,首先要了解线性参考技术。线性参考是一种采用沿具有测量值的线性要素的相对位置来描述和存储地理位置的方法,即使用距离来定位沿线的事件。这里的距离表示一个度量值,可以是长度,也可以是时间、费用等。
下图是线性参考的简单示意,图中底部的线是一条具有测量值的线段(比如公路、管道等),线上方的点和线段是发生在该线段上的事件(如公路上的交通事故、一段道路的路面材料等)。线性参考技术将图中沿线的点和线从左至右分别描述为:距离线段起始位置12个单位的点,沿线段第35个单位开始至第76个单位结束的线段,沿线段第84.3个单位的点。
在很多实际应用中,使用线性参考进行定位比传统的通过精确的 X、Y 坐标来定位更符合人们的习惯,从而能够更加有效地处理问题。比如在某某路口东300米处发生交通事故,比描述为发生在(6570.3876,3589.6082)坐标处更容易定位。
动态分段技术就是基于线性参考技术发展起来的。它主要使用两种数据结构:路由数据集和事件表。路由数据集中的路由对象就是线性参考中“具有测量值的线性要素”,它与普通线对象的区别是除X、Y坐标外还存储有第三维信息,即用于度量的测量值;而事件表是一个属性表,其中的每一条记录都存储了一个用于对应路由对象的标识值,以及相应的测量值,即相对位置信息。如下图所示,动态分段的核心过程就是通过事件表中记录的标识值和相对位置信息,将事件表中的每一条记录对应到路由上,动态地生成为点或者线对象。用户可以存储生成的点或线数据,也可以不存储,因为该数据在使用前可以通过事件表和路由快速地动态生成。
除了使用相对位置描述发生在线上的事件,比传统GIS要素更容易定位外,动态分段技术主要解决了传统GIS中的两个问题。
- 提高数据制作效率和降低数据存储空间。
- 降低数据维护的复杂度。
众所周知,传统GIS中的线性要素只能具有一维属性,要描述线性对象的多个属性时,需要多份线性空间数据。以最为常见的公路为例,要存储公路的路况、路宽、路面材料和铺设年份四个属性,就要分别根据这些属性制作四份线数据。而实际应用中,线要素对应属性是几十、几百的,每个属性都要建立一份空间数据,这不仅增加了数据量,还降低了分析效率,也增加了应用的复杂度。
而动态分段的特点就是,允许线要素具有多维属性,一份空间数据,一个或几个属性表数据,即可解决问题。使用动态分段技术,可以通过四个事件表来分别记录公路的路况、路宽、路面材料和铺设年份信息,在每个事件表中,使用一个字段来存储该记录对应的路由对象的唯一标识值,使用两个属性字段分别存储该条记录在公路上的起始位置和终止位置,通过这三个属性字段,就能够将属性表中的记录定位到路由数据上,根据属性表中记录与路由数据的对应关系动态地生成表达某个属性的空间数据。
当描述线数据的属性发生变化时,在传统 GIS 中,就要修改属性对应的空间数据。当属性频繁变化时,将使数据的维护工作变得十分繁琐复杂。例如,一般情况下,路况信息需要半小时更新一次,这对于传统GIS工作量的挑战,是巨大的,而使用动态分段技术可以避免这种麻烦,仅需要每隔半小时,修改一下属性对应的数值即可,这极大降低了数据维护的复杂度,使得某些应用变成可能。
-
动态分段的特点
- 不需要重复数字化就可以进行多个属性集的动态显示和分析,有效减少冗余数据。
- 并没有按照属性数据集对线路进行真正的分段,只是在需要查询、分析时,动态完成各种属性数据的分段显示。
- 所有属性数据集都建立在同一线路位置描述的基础上,即属性数据组织独立于线路位置描述,独立于线路基础底图,因此易于数据的更新和维护。
- 可进行多个属性数据集的综合查询和分析。
- 路由、事件表与空间数据的联动:在 SuperMap 中,通过路由和事件表生成空间数据之后,系统内部就建立了三者间的动态分段关系,就可以实现路由、事件表和空间数据的联动修改,详细介绍请参见
generateSpatialData
方法。
-
动态分段的基本概念
在SuperMap中,动态分段主要涉及两种数据结构:路由和事件。路由用来表达具有测量值的线对象,事件记录发生在路由上的现象的位置和其他属性。
路由:是使用唯一 ID 标识,并具有度量值的线对象。除有 X、Y 坐标外,每个节点还有一个用于度量的值(刻度值),是路由与一般线对象的根本区别。在 SuperMap 中,使用
GeoLineM
类型来描述路由对象。路由对象可以用来模拟现实世界中的公路、铁路、河流和管线等线性地物。存储了路由对象的数据集,称为路由数据集,是一个矢量数据集。刻度值(M 值):SuperMap 中,路由的节点信息由(X、Y、M)表达,如下图所示,为某个路由对象的节点信息。刻度值即 M 值,代表该节点到路由起点的度量值,该值可以是距离、时间或其他任何值。M 值独立于路由数据的坐标系统,其单位可以不与(X,Y)的坐标单位相同。M 值可以递增、递减或者保持不变。
路由位置:路由的一个点或路由上一部分的位置,简称位置。分为点路由位置和线路由位置。点路由位置使用一个刻度值描述沿路由的一个位置,如某某路500米处;线路由位置使用起始刻度值和终止刻度值来描述路由上一部分,如某某路200到1000米处。
事件:包含路由位置及相关属性的一条记录称为路由事件,简称事件。存储了路由事件集合的属性表称为事件表。与路由位置对应,事件也分为点事件和线事件,分别存储于点事件表和线事件表中。点事件和线事件请参见
EventType
类型。零长度事件:是指起始刻度与终止刻度相同的线事件。如果允许设置一个容限值,那么起始刻度与终止刻度的差值的绝对值小于该容限时,也可看做是零长度事件。
路由标识字段:路由数据集中的一个字段,存储了路由 ID,是路由对象的唯一标识字段。路由数据集、事件表和通过事件表生成的空间数据中均包含该字段,它将事件与路由或空间数据对应起来。
插值求 M 值:通过外部数据或路由对象本身已知的刻度值,可以利用插值方法来估算路由上其他节点的刻度值。插值方法分为内插和外推两种,外推又可分为向前外推和向后外推 。内插即在数列的已知值之间估计中间各点的值,而外推即估算数列已知数值范围以外的各个值。如下图所示,节点1的 M 值可由点2、4通过向前外推得出,节点3和5的 M 值可由点2、4、6进行内插获得,节点7的 M 值则可以由点4、6通过向后外推得出。
-
动态分段的一般过程
SuperMap提供的动态分段的主要功能包括:生成路由数据集、生成事件表、事件表的叠加与融合、生成空间数据。实现动态分段的一般过程为:
- 首先获取或生成路由数据集(
generateRoutes
方法); - 对路由数据集进行校准(
calibrateRoutes
方法); - 然后生成事件表(
generateEventTable
方法),并根据实际需求对事件表进行叠加(overlayRouteEvents
方法)、融合(dissolveRouteEvents
方法)或其他修改处理; - 接着由事件表创建对应的空间数据(
generateSpatialData
方法),可以进行路由数据集、事件表和空间数据的联动修改,以及重新生成空间数据(rebuildSpatialData
方法); - 生成空间数据后,还可以根据研究内容做进一步的处理和分析。
- 首先获取或生成路由数据集(
-
注意事项:
- 动态分段功能中,对数据集中的路由 ID 字段和刻度值字段(点事件对应刻度值字段,线事件对应起始刻度字段和终止刻度字段)的字段类型有一定限制,下表列出了其对字段类型(请参见
FieldType
类)的支持情况。注意:其中宽字符和文本型字段的值只能由英文字符、数字或者英文加数字构成,不能包含其他文字或者符号。 - 动态分段关系
动态分段关系在生成空间数据时建立,即根据路由 ID、刻度值字段等信息建立起路由数据集、事件表和生成的空间数据三者的对应关系。动态分段关系主要用于实现三个角色间的联动修改,并可能影响空间数据的生成及联动修改,详细介绍请参见
generateSpatialData
方法。 - 动态分段功能中,对数据集中的路由 ID 字段和刻度值字段(点事件对应刻度值字段,线事件对应起始刻度字段和终止刻度字段)的字段类型有一定限制,下表列出了其对字段类型(请参见
要获取动态分段更为详细的介绍,还可以阅读《动态分段》技术文档。
-
-
-
方法概要
所有方法 静态方法 具体方法 已过时的方法 限定符和类型 方法和说明 static void
addSteppedListener(SteppedListener l)
添加一个进度条事件(SteppedEvent
)的监听器。static DatasetVector
calibrateRoutes(DatasetVector referenceLineM, String routeIDField, DatasetVector calibratePointDataset, String calibrateRouteID, String measureField, CalibrateOptions options, Datasource outputDatasource, String outputDatasetName)
已过时。此方法已废弃,请使用支持进度监听的新方法#compileSSCData(SSCCompilerParameter, SteppedListener...)
替换。static DatasetVector
calibrateRoutes(DatasetVector referenceLineM, String routeIDField, DatasetVector calibratePointDataset, String calibrateRouteID, String measureField, CalibrateOptions options, Datasource outputDatasource, String outputDatasetName, SteppedListener... listeners)
根据参考点的刻度校准路由数据集。static DatasetVector
createMarkPoints(CreateMarkPointsParameter parameter)
已过时。此方法已废弃,请使用支持进度监听的新方法LinearReferencing.createMarkPoints(CreateMarkPointsParameter, SteppedListener...)
替换。static DatasetVector
createMarkPoints(CreateMarkPointsParameter parameter, SteppedListener... listeners)
创建路由数据中刻度值点。static DatasetVector
dissolveRouteEvents(RouteEventsParameter inputEventsParameter, String[] dissolveFields, EventDissolveType eventDissolveType, Datasource outputDatasource, String outputDatasetName, RouteEventsParameter resultEventsParameter, String[] statisticFields, StatisticsType[] statisticModes, double tolerance)
static DatasetVector
dissolveRouteEvents(RouteEventsParameter inputEventsParameter, String[] dissolveFields, EventDissolveType eventDissolveType, Datasource outputDatasource, String outputDatasetName, RouteEventsParameter resultEventsParameter, String[] statisticFields, StatisticsType[] statisticModes, double tolerance, SteppedListener... listeners)
融合事件表。static DatasetVector
generateEventTable(DatasetVector referenceLineM, GenerateEventTableParameter parameter)
已过时。此方法已废弃,请使用支持进度监听的新方法#compileSSCData(SSCCompilerParameter, SteppedListener...)
替换。static DatasetVector
generateEventTable(DatasetVector referenceLineM, GenerateEventTableParameter parameter, SteppedListener... listeners)
根据空间数据创建事件表。static DatasetVector
generateRoutes(DatasetVector referenceLine, GenerateRoutesParameter parameter)
已过时。此方法已废弃,请使用支持进度监听的新方法LinearReferencing.generateRoutes(DatasetVector, GenerateRoutesParameter, SteppedListener...)
替换。static DatasetVector
generateRoutes(DatasetVector referenceLine, GenerateRoutesParameter parameter, SteppedListener... listeners)
生成路由数据集。static DatasetVector
generateSpatialData(GenerateSpatialDataParameter parameter)
已过时。此方法已废弃,请使用支持进度监听的新方法#compileSSCData(SSCCompilerParameter, SteppedListener...)
替换。static DatasetVector
generateSpatialData(GenerateSpatialDataParameter parameter, SteppedListener... listeners)
根据点或线事件表生成空间数据。static DatasetVector
overlayRouteEvents(RouteEventsParameter inputEventsParameter, RouteEventsParameter overlayEventParameter, EventOverlayType eventOverlayType, Datasource outputDatasource, String outputDatasetName, RouteEventsParameter resultEventsParameter, double tolerance, boolean isKeepField, boolean isKeepZeroLengthEvents)
static DatasetVector
overlayRouteEvents(RouteEventsParameter inputEventsParameter, RouteEventsParameter overlayEventParameter, EventOverlayType eventOverlayType, Datasource outputDatasource, String outputDatasetName, RouteEventsParameter resultEventsParameter, double tolerance, boolean isKeepField, boolean isKeepZeroLengthEvents, SteppedListener... listeners)
叠加事件表。static boolean
rebuildSpatialData(DatasetVector eventTable)
已过时。此方法已废弃,请使用支持进度监听的新方法LinearReferencing.rebuildSpatialData(DatasetVector, SteppedListener...)
替换。static boolean
rebuildSpatialData(DatasetVector eventTable, SteppedListener... listeners)
当已存在动态分段关系的事件表被修改后,重新生成对应的空间数据。static void
removeSteppedListener(SteppedListener l)
移除一个进度条事件(SteppedEvent
)的监听器。
-
-
-
方法详细资料
-
generateRoutes
@Deprecated public static DatasetVector generateRoutes(DatasetVector referenceLine, GenerateRoutesParameter parameter)
已过时。 此方法已废弃,请使用支持进度监听的新方法LinearReferencing.generateRoutes(DatasetVector, GenerateRoutesParameter, SteppedListener...)
替换。生成路由数据集。实现动态分段的首要步骤是获得路由数据。每一条路由具有刻度值和唯一标识值,生成事件表时,事件发生的路由和刻度值(线事件包含起始和终止刻度值), 需要参考路由数据集中的路由 ID 和 M 值。
路由数据可以是已有的(通过数字化工作获得,或是从外部及其他格式导入),也可以由线数据通过一定方式生成。 该方法即用于根据一个线数据集来构建相应的路由数据集。
SuperMap 提供了四种生成路由数据集的方式,分别是:线参考点刻度方式、线单字段方式、线双字段方式和线长度方式。关于这四种生成路由方式的介绍,请参见
GenerateType
类。注意:生成路由前,最好对用于生成路由的线数据进行去除重复节点处理。如果线对象具有重复节点,即相同坐标的节点,对应生成的路由可能产生“两个或多个相同的点具有相同的刻度值”的情况,可能破坏路由刻度值的单调性(递增、递减或保持不变),从而导致后续的动态分段分析结果不正确。
- 参数:
referenceLine
- 指定的参考道路线数据集。要求数据集类型为线数据集,输入其他类型的数据集将导致生成路由失败并返回 null。parameter
- 指定的生成参数。- 返回:
- 创建好的路由数据集。
- 示范代码:
- 以下代码示范了如何通过“线参考点刻度”方式生成路由数据集。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace)
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void GenerateRoutesExample() { //获取用于生成路由的线数据和参考点数据 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector datasetLine = (DatasetVector) datasource.getDatasets().get( "Roads"); DatasetVector datasetPoint = (DatasetVector) datasource.getDatasets().get( "PointEvent"); //构造一个 GenerateRoutesParameter 对象并设置相关参数 GenerateRoutesParameter parameter = new GenerateRoutesParameter(); parameter.setType(GenerateType.BY_POINT);//使用“线参考点刻度”方式来生成路由数据集 parameter.setDatasetPoint(datasetPoint); parameter.setLineRouteIDField("ROUTEID"); parameter.setPointRouteIDField("ROUTEID"); parameter.setMeasureField("MEASURE"); parameter.setErrorInfoField("ERROR"); parameter.setOutputDatasource(datasource); parameter.setOutputDatasetName("Routes"); parameter.setTolerance(0.179316666); if (datasource.getDatasets().contains("Routes")) { // 判断该数据集是否存在动态分段关系,如存在则删除关系 DatasetVector dynamicDataset = (DatasetVector) datasource .getDatasets().get("Routes"); DynamicSegmentInfo[] infos= DynamicSegmentManager.getDynamicSegmentInfos(dynamicDataset); if(infos.length!=0){ DynamicSegmentManager.removeDynamicSegmentInfos(dynamicDataset); } datasource.getDatasets().delete("Routes"); } //调用 GenerateRoutes 方法来生成路由数据集 DatasetVector resultRoutesDataset = LinearReferencing.generateRoutes( datasetLine, parameter); //加载到当前地图上 mapControl.getMap().getLayers().add(resultRoutesDataset, true); mapControl.getMap().refresh(); }
-
generateRoutes
public static DatasetVector generateRoutes(DatasetVector referenceLine, GenerateRoutesParameter parameter, SteppedListener... listeners)
生成路由数据集。实现动态分段的首要步骤是获得路由数据。每一条路由具有刻度值和唯一标识值,生成事件表时,事件发生的路由和刻度值(线事件包含起始和终止刻度值), 需要参考路由数据集中的路由 ID 和 M 值。
路由数据可以是已有的(通过数字化工作获得,或是从外部及其他格式导入),也可以由线数据通过一定方式生成。 该方法即用于根据一个线数据集来构建相应的路由数据集。
SuperMap 提供了四种生成路由数据集的方式,分别是:线参考点刻度方式、线单字段方式、线双字段方式和线长度方式。关于这四种生成路由方式的介绍,请参见
GenerateType
类。注意:生成路由前,最好对用于生成路由的线数据进行去除重复节点处理。如果线对象具有重复节点,即相同坐标的节点,对应生成的路由可能产生“两个或多个相同的点具有相同的刻度值”的情况,可能破坏路由刻度值的单调性(递增、递减或保持不变),从而导致后续的动态分段分析结果不正确。
- 参数:
referenceLine
- 指定的参考道路线数据集。要求数据集类型为线数据集,输入其他类型的数据集将导致生成路由失败并返回 null。parameter
- 指定的生成参数。listeners
- 用于接收进度条事件的监听器。- 返回:
- 创建好的路由数据集。
- 示范代码:
- 以下代码示范了如何通过“线参考点刻度”方式生成路由数据集。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace)
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void GenerateRoutesExample() { //获取用于生成路由的线数据和参考点数据 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector datasetLine = (DatasetVector) datasource.getDatasets().get( "Roads"); DatasetVector datasetPoint = (DatasetVector) datasource.getDatasets().get( "PointEvent"); //构造一个 GenerateRoutesParameter 对象并设置相关参数 GenerateRoutesParameter parameter = new GenerateRoutesParameter(); parameter.setType(GenerateType.BY_POINT);//使用“线参考点刻度”方式来生成路由数据集 parameter.setDatasetPoint(datasetPoint); parameter.setLineRouteIDField("ROUTEID"); parameter.setPointRouteIDField("ROUTEID"); parameter.setMeasureField("MEASURE"); parameter.setErrorInfoField("ERROR"); parameter.setOutputDatasource(datasource); parameter.setOutputDatasetName("Routes"); parameter.setTolerance(0.179316666); if (datasource.getDatasets().contains("Routes")) { // 判断该数据集是否存在动态分段关系,如存在则删除关系 DatasetVector dynamicDataset = (DatasetVector) datasource .getDatasets().get("Routes"); DynamicSegmentInfo[] infos= DynamicSegmentManager.getDynamicSegmentInfos(dynamicDataset); if(infos.length!=0){ DynamicSegmentManager.removeDynamicSegmentInfos(dynamicDataset); } datasource.getDatasets().delete("Routes"); } //调用 GenerateRoutes 方法来生成路由数据集 DatasetVector resultRoutesDataset = LinearReferencing.generateRoutes( datasetLine, parameter); //加载到当前地图上 mapControl.getMap().getLayers().add(resultRoutesDataset, true); mapControl.getMap().refresh(); }
-
calibrateRoutes
@Deprecated public static DatasetVector calibrateRoutes(DatasetVector referenceLineM, String routeIDField, DatasetVector calibratePointDataset, String calibrateRouteID, String measureField, CalibrateOptions options, Datasource outputDatasource, String outputDatasetName)
已过时。 此方法已废弃,请使用支持进度监听的新方法#compileSSCData(SSCCompilerParameter, SteppedListener...)
替换。根据参考点的刻度校准路由数据集。- 为什么要校准路由?
- 如何校准?
- 首先通过路由标识字段值将参考点与路由对应起来(参考点数据和路由数据各有一个路由标识字段,与路由数据路由 ID 相同的参考点,视为与路由对应的参考点);
- 然后,当对应参考点落在路由上并与某一节点重合时,该节点的 M 值使用该参考点的 M 值;
- 路由上未与对应参考点重叠的节点的 M,使用位于校准容限(请参见
setTolerance
方法的介绍)范围内的参考点的 M 值插值获得。并且,这些位于校准容限内的参考点,在对应路由上的垂足位置生成新的节点,并将对应参考点的 M 值赋予该节点。如下图中的参考点 c1、c2,其到路由的最短距离小于校准容限,因此会在路由上对应位置添加对应节点; - 位于校准容限范围之外的参考点将不参与校准。下图中的参考点 c3在校准容限范围外,因此它不会参与校准,也不会在路由上生成新的节点。
- 校准路由应用实例
精确的度量值,才能够保证事件被正确定位,因此精确的路由数据对动态分段是至关重要的。如果路由数据的刻度值可能不准确,或者需要更新路由数据的刻度值,我们可以通过使用可靠的参考点数据对路由数据的刻度值进行校准。尤其是在用这些刻度值连接大量的事件数据时,校准路由数据集更是必不可少的一项工作。
校准路由是读取参考点的刻度值信息来调整路由刻度值的过程。
SuperMap 提供了两种校准模式:按距离校准(ByDistance)和按刻度值校准(ByMeasure),关于两种模式如何对路由进行校准请参见
CalibrateMode
枚举类型。使用该方法校准路由时,除指定路由数据集及其路由标识字段、参考点数据及其路由标识字段和刻度字段外,还需要通过一个校准选项(
CalibrateOptions
)对象来设置校准路由的其他参数,如校准模式、校准容限及单位等。现有一份高速公路的路由数据,其刻度值为高速公路的里程信息,但刻度值可能不够准确。因此,派出测量人员沿高速公路每隔200米采集一个采样点,并通过仪器测量和记录相应的里程值。然后使用这批数据作为参考点数据,对已有的高速公路路由数据进行校准来获得最新的、准确的里程信息。
- 参数:
referenceLineM
- 指定的需要被校准的路由数据集。要求数据集类型为路由数据集,输入其他类型的数据集将导致校准路由失败并返回 null。routeIDField
- 指定的路由数据集中的路由标识字段。该字段对字段类型有要求,请参见LinearReferencing
类的介绍。如果设置的类型不被支持,会导致校准失败。calibratePointDataset
- 指定的用于校准路由的参考点数据集,该数据集中有表示刻度的字段。要求数据集类型为点数据集,输入其他类型的数据集将导致校准路由失败并返回 null。calibrateRouteID
- 指定的参考点数据集中的路由标识字段。该字段对字段类型有要求,请参见LinearReferencing
类的介绍。如果设置的类型不被支持,会导致校准失败。measureField
- 指定的参考点数据集中用于表示刻度值的字段。该字段对字段类型有要求,请参见LinearReferencing
类的介绍。如果设置的类型不被支持,会导致校准失败。options
- 指定的校准选项。outputDatasource
- 指定的结果路由数据集所在的数据源。如果为 null,系统会自动将结果数据集保存到被校准的路由数据集所在的数据源中。outputDatasetName
- 指定的结果路由数据集的名称。- 返回:
- 校准之后的路由数据集,如果失败则返回 null。
-
calibrateRoutes
public static DatasetVector calibrateRoutes(DatasetVector referenceLineM, String routeIDField, DatasetVector calibratePointDataset, String calibrateRouteID, String measureField, CalibrateOptions options, Datasource outputDatasource, String outputDatasetName, SteppedListener... listeners)
根据参考点的刻度校准路由数据集。- 为什么要校准路由?
- 如何校准?
- 首先通过路由标识字段值将参考点与路由对应起来(参考点数据和路由数据各有一个路由标识字段,与路由数据路由 ID 相同的参考点,视为与路由对应的参考点);
- 然后,当对应参考点落在路由上并与某一节点重合时,该节点的 M 值使用该参考点的 M 值;
- 路由上未与对应参考点重叠的节点的 M,使用位于校准容限(请参见
setTolerance
方法的介绍)范围内的参考点的 M 值插值获得。并且,这些位于校准容限内的参考点,在对应路由上的垂足位置生成新的节点,并将对应参考点的 M 值赋予该节点。如下图中的参考点 c1、c2,其到路由的最短距离小于校准容限,因此会在路由上对应位置添加对应节点; - 位于校准容限范围之外的参考点将不参与校准。下图中的参考点 c3在校准容限范围外,因此它不会参与校准,也不会在路由上生成新的节点。
- 校准路由应用实例
精确的度量值,才能够保证事件被正确定位,因此精确的路由数据对动态分段是至关重要的。如果路由数据的刻度值可能不准确,或者需要更新路由数据的刻度值,我们可以通过使用可靠的参考点数据对路由数据的刻度值进行校准。尤其是在用这些刻度值连接大量的事件数据时,校准路由数据集更是必不可少的一项工作。
校准路由是读取参考点的刻度值信息来调整路由刻度值的过程。
SuperMap 提供了两种校准模式:按距离校准(ByDistance)和按刻度值校准(ByMeasure),关于两种模式如何对路由进行校准请参见
CalibrateMode
枚举类型。使用该方法校准路由时,除指定路由数据集及其路由标识字段、参考点数据及其路由标识字段和刻度字段外,还需要通过一个校准选项(
CalibrateOptions
)对象来设置校准路由的其他参数,如校准模式、校准容限及单位等。现有一份高速公路的路由数据,其刻度值为高速公路的里程信息,但刻度值可能不够准确。因此,派出测量人员沿高速公路每隔200米采集一个采样点,并通过仪器测量和记录相应的里程值。然后使用这批数据作为参考点数据,对已有的高速公路路由数据进行校准来获得最新的、准确的里程信息。
- 参数:
referenceLineM
- 指定的需要被校准的路由数据集。要求数据集类型为路由数据集,输入其他类型的数据集将导致校准路由失败并返回 null。routeIDField
- 指定的路由数据集中的路由标识字段。该字段对字段类型有要求,请参见LinearReferencing
类的介绍。如果设置的类型不被支持,会导致校准失败。calibratePointDataset
- 指定的用于校准路由的参考点数据集,该数据集中有表示刻度的字段。要求数据集类型为点数据集,输入其他类型的数据集将导致校准路由失败并返回 null。calibrateRouteID
- 指定的参考点数据集中的路由标识字段。该字段对字段类型有要求,请参见LinearReferencing
类的介绍。如果设置的类型不被支持,会导致校准失败。measureField
- 指定的参考点数据集中用于表示刻度值的字段。该字段对字段类型有要求,请参见LinearReferencing
类的介绍。如果设置的类型不被支持,会导致校准失败。options
- 指定的校准选项。outputDatasource
- 指定的结果路由数据集所在的数据源。如果为 null,系统会自动将结果数据集保存到被校准的路由数据集所在的数据源中。outputDatasetName
- 指定的结果路由数据集的名称。listeners
- 用于接收进度条事件的监听器。- 返回:
- 校准之后的路由数据集,如果失败则返回 null。
-
generateEventTable
@Deprecated public static DatasetVector generateEventTable(DatasetVector referenceLineM, GenerateEventTableParameter parameter)
已过时。 此方法已废弃,请使用支持进度监听的新方法#compileSSCData(SSCCompilerParameter, SteppedListener...)
替换。根据空间数据创建事件表。- 事件表和事件表的类型
- 如何获取事件表
- 一种是人工建立一个属性表,添加路由标识字段、刻度字段和其他属性字段,并输入相应的属性信息来生成事件表。 这种方式虽然简单但往往需要耗费较多的人力物力。
- 另一种方式是通过点或线空间数据(称为事件数据)和用于参考的路由数据来自动生成事件表。生成的事件的刻度值和位于哪条路由需要从该路由数据中获得。
- 根据点或线数据生成事件表
- 点事件表的生成
- 线事件表的生成
事件表实际上就是一个属性表,其中的每一条记录代表了一个事件,除了必须包含的路由标识字段、事件在路由上的刻度字段外, 还可以包括其他用于描述事件的属性信息。
事件表的类型由其存储的事件类型决定,分为点事件表和线事件表,分别存储了点事件和线事件的集合。有关事件类型请参见
EventType
类的介绍。获取事件表有两种方式:
由二维点数据和路由数据集可以生成点事件表。下图是点事件的生成示意图,粉色区域是以给定的查找半径为半径,对路由对象生成的一个缓冲区域,称为查找范围。 落在该区域内的点用于生成事件表 ,每个点将对应一个事件(事件表中的一条记录)。生成的点事件表,除包含系统字段外,还会增加两个属性字段,分别用于存储对应路由的路由 ID 和点到路由的垂足点的位置的 M 值(作为该点事件的刻度值)。而查找范围之外的点不会生成事件(如 p2 点)。
与点事件表的生成类似,如果二维线对象完全落入查找范围内,每条线将会生成一个线事件,属性字段包含路由 ID、线的起点到路由的垂足点位置的 M 值(作为线事件的起始刻度值)和线的终点到路由的垂足点位置的 M 值(作为终止刻度值);未落入或部分落入查找范围的线对象将不会生成线事件。下图是生成线事件表的示意图 ,线l2到路由的最大直线距离大于查找半径,因此,不会生成对应的事件。
使用该方法生成事件表时,除指定参考的路由数据集外,还需要通过一个
GenerateEventTableParameter
对象来设置其他生成事件表的参数,如事件数据、路由标识字段、查找半径等。- 参数:
referenceLineM
- 指定的关联路由数据集。parameter
- 指定的生成事件表参数设置。- 返回:
- 一个属性表数据集,即事件表。
- 示范代码:
- 以下代码示范了如何生成点事件表。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void GenerateEventTableExample() { //获取用于生成事件表的路由和点数据 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector datasetRoute = (DatasetVector) datasource.getDatasets().get( "Roads_M"); DatasetVector datasetPoint = (DatasetVector) datasource.getDatasets().get( "PointEvent"); //构造一个 GenerateEventTableParameter 对象并设置相关参数 GenerateEventTableParameter parameter = new GenerateEventTableParameter(); parameter.setEventDataset(datasetPoint); parameter.setRouteIDField("ROUTEID"); parameter.setSearchRadius(0.001); parameter.setRetainingAllFields(true); parameter.setOutputDatasetRouteField("ROUTEID"); parameter.setMeasureField("MEASURE"); parameter.setFindingClosestRoute(true); parameter.setOutputDatasource(datasource); parameter.setOutputDatasetName("Point_EventTable"); if (datasource.getDatasets().contains("Point_EventTable")) { // 判断该数据集是否存在动态分段关系,如存在则删除关系 DatasetVector dynamicDataset = (DatasetVector) datasource .getDatasets().get("Point_EventTable"); DynamicSegmentInfo[] infos = DynamicSegmentManager .getDynamicSegmentInfos(dynamicDataset); if (infos.length != 0) { DynamicSegmentManager.removeDynamicSegmentInfos(dynamicDataset); } datasource.getDatasets().delete("Point_EventTable"); } //调用 GenerateEventTable 方法来生成事件表 DatasetVector resultTable = LinearReferencing.generateEventTable( datasetRoute, parameter); if (resultTable != null) { JOptionPane.showMessageDialog(null, "生成事件表成功"); } }
-
generateEventTable
public static DatasetVector generateEventTable(DatasetVector referenceLineM, GenerateEventTableParameter parameter, SteppedListener... listeners)
根据空间数据创建事件表。- 事件表和事件表的类型
- 如何获取事件表
- 一种是人工建立一个属性表,添加路由标识字段、刻度字段和其他属性字段,并输入相应的属性信息来生成事件表。 这种方式虽然简单但往往需要耗费较多的人力物力。
- 另一种方式是通过点或线空间数据(称为事件数据)和用于参考的路由数据来自动生成事件表。生成的事件的刻度值和位于哪条路由需要从该路由数据中获得。
- 根据点或线数据生成事件表
- 点事件表的生成
- 线事件表的生成
事件表实际上就是一个属性表,其中的每一条记录代表了一个事件,除了必须包含的路由标识字段、事件在路由上的刻度字段外, 还可以包括其他用于描述事件的属性信息。
事件表的类型由其存储的事件类型决定,分为点事件表和线事件表,分别存储了点事件和线事件的集合。有关事件类型请参见
EventType
类的介绍。获取事件表有两种方式:
由二维点数据和路由数据集可以生成点事件表。下图是点事件的生成示意图,粉色区域是以给定的查找半径为半径,对路由对象生成的一个缓冲区域,称为查找范围。 落在该区域内的点用于生成事件表 ,每个点将对应一个事件(事件表中的一条记录)。生成的点事件表,除包含系统字段外,还会增加两个属性字段,分别用于存储对应路由的路由 ID 和点到路由的垂足点的位置的 M 值(作为该点事件的刻度值)。而查找范围之外的点不会生成事件(如 p2 点)。
与点事件表的生成类似,如果二维线对象完全落入查找范围内,每条线将会生成一个线事件,属性字段包含路由 ID、线的起点到路由的垂足点位置的 M 值(作为线事件的起始刻度值)和线的终点到路由的垂足点位置的 M 值(作为终止刻度值);未落入或部分落入查找范围的线对象将不会生成线事件。下图是生成线事件表的示意图 ,线l2到路由的最大直线距离大于查找半径,因此,不会生成对应的事件。
使用该方法生成事件表时,除指定参考的路由数据集外,还需要通过一个
GenerateEventTableParameter
对象来设置其他生成事件表的参数,如事件数据、路由标识字段、查找半径等。- 参数:
referenceLineM
- 指定的关联路由数据集。parameter
- 指定的生成事件表参数设置。listeners
- 用于接收进度条事件的监听器。- 返回:
- 一个属性表数据集,即事件表。
- 示范代码:
- 以下代码示范了如何生成点事件表。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void GenerateEventTableExample() { //获取用于生成事件表的路由和点数据 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector datasetRoute = (DatasetVector) datasource.getDatasets().get( "Roads_M"); DatasetVector datasetPoint = (DatasetVector) datasource.getDatasets().get( "PointEvent"); //构造一个 GenerateEventTableParameter 对象并设置相关参数 GenerateEventTableParameter parameter = new GenerateEventTableParameter(); parameter.setEventDataset(datasetPoint); parameter.setRouteIDField("ROUTEID"); parameter.setSearchRadius(0.001); parameter.setRetainingAllFields(true); parameter.setOutputDatasetRouteField("ROUTEID"); parameter.setMeasureField("MEASURE"); parameter.setFindingClosestRoute(true); parameter.setOutputDatasource(datasource); parameter.setOutputDatasetName("Point_EventTable"); if (datasource.getDatasets().contains("Point_EventTable")) { // 判断该数据集是否存在动态分段关系,如存在则删除关系 DatasetVector dynamicDataset = (DatasetVector) datasource .getDatasets().get("Point_EventTable"); DynamicSegmentInfo[] infos = DynamicSegmentManager .getDynamicSegmentInfos(dynamicDataset); if (infos.length != 0) { DynamicSegmentManager.removeDynamicSegmentInfos(dynamicDataset); } datasource.getDatasets().delete("Point_EventTable"); } //调用 GenerateEventTable 方法来生成事件表 DatasetVector resultTable = LinearReferencing.generateEventTable( datasetRoute, parameter); if (resultTable != null) { JOptionPane.showMessageDialog(null, "生成事件表成功"); } }
-
generateSpatialData
@Deprecated public static DatasetVector generateSpatialData(GenerateSpatialDataParameter parameter)
已过时。 此方法已废弃,请使用支持进度监听的新方法#compileSSCData(SSCCompilerParameter, SteppedListener...)
替换。根据点或线事件表生成空间数据。成功则返回定位后的点或者线数据集,如果是线事件表,生成的是路由数据集。事件表用属性表的方式记录了点或者线事件发生所在的路由、刻度、事件的描述信息(如交通事故发生地的天气状况、驾驶者的酒精含量、当时的车速、路面宽度、 铺设材料等 )。如下图所示,生成空间数据就是根据路由数据集,将事件表中的事件定位到空间上,生成相应的点或者线数据,并建立和存储三者间的动态分段关系的过程 。其中点事件对应生成点数据集 ,线事件表对应生成的线数据为路由数据集。动态分段关系隐含存储在数据集中,记录了路由数据集、事件表与生成的空间数据三者间的对应关系 ,是进行联动修改(即修改三者中的一个,其他两个根据规则自动进行修改)也就是动态分段的依据。
- 生成的空间数据的类型
- 动态分段关系
- 路由、事件表和空间数据的联动
- 事件的描述信息发生变化。这种情况在事件表与空间数据之间发生联动。
-
事件发生的路由位置发生变化。这种情况在事件表与空间数据之间发生动态变化。
修改事件发生的位置,是指修改事件表或空间数据中的刻度值字段。如果修改事件表中某条记录(事件)的刻度值, 那么对应的空间数据中该事件对应的点或者线对象的几何信息和属性表中对应记录的刻度字段也会做相应修改 ;如果修改生成的空间数据的属性表中的刻度字段的值,对应的对象的几何信息也会修改 ,事件表中的相关联的事件的刻度字段的值也会动态发生同等变化。如果是线事件 ,可以修改起始刻度或者终止刻度,事件的长度和位置可能发生变化。如下图所示,是生成空间数据之后 ,将对应事件表中第一条事件的起始刻度和终止刻度由(20.78 ,79.37)修改为(150.00,180.00)前后,对应空间数据中对应该事件的线的变化 ,可以看出,当事件的刻度值发生变化后,对应的空间数据也自动进行对应的修改。
-
事件发生的路由改变。这种情况下,空间数据会根据路由数据集的修改发生变化,而修改空间数据时,对应的路由数据不会发生变化; 事件表与空间数据之间会发生联动修改。
这种情况适用于由于数据错误或者变更导致事件所发生的路由需要修改的情形,具体分为以下三种情形:
- 如果修改的是路由对象的空间几何信息,对应的空间数据中相关对象的几何信息也会自动修改。如果发生事件的路由的位置和刻度值发生变化, 如管道维修后走向发生了变化,它的形状和刻度值可能都需要修改。这时就需要对路由对象本身的空间几何信息进行修改,如旋转、移动,修改刻度值等。修改后, 对应的空间数据中相关对象的几何信息会作相应的变化,即对应的事件和空间数据将重新定位。
- 如果修改的是事件表的中某记录的路由 ID,则空间数据中与之关联的对象的几何信息和属性表中的路由ID字段也会随之动态改变。如下图中的事件表及其对应的空间数据,将事件表中第一条记录的路由 ID 由1改为2之后,该记录对应的空间数据也发生了变化,被定位到了 ID 为2的路由上面,正如下图(下)所展示的一样。
- 如果修改的是生成的空间数据的路由 ID,则事件表中对应记录的路由 ID 值也会改变,同时,空间数据的几何信息也会根据修改后对应的路由而进行修改。
- 注意:
- 用于生成空间数据的事件表中必须包含路由标识字段和刻度字段(点事件包含刻度字段,线事件包含起始刻度字段和终止刻度字段)。 路由标识字段的值用于将事件对应的点或线定位到正确的路由上 ,刻度字段的值使事件对应的点或线最终正确定位。事件表中的路由标识字段、刻度字段及其他描述事件的属性,都会写入生成的空间数据的属性表中。
- 通过该方法生成空间数据时,系统会在结果数据集中添加一个名为“Event_SMID”的字段,用于存储事件表中对应事件的 SMID。特别需要注意的是,不能修改该字段,否则可能导致联动的结果错误。
- 由于事件表与空间数据为一对一关系,如果某事件表已经具有了一个动态分段关系,则不能再次用于其他的生成空间数据,除非将其关系删除。因此,在调用
GenerateSpatialData 方法生成空间数据前,应先使用
DynamicSegmentManager
类的 getDynamicSegmentInfos 方法检查事件表是否存在动态分段关系,如果存在则调用 removeDynamicSegmentInfos 方法删除关系。但请注意,可以使用rebuildSpatialData
方法重新生成同名的空间数据,此时不必删除动态分段关系。 - 校准、事件表融合、线参考点刻度生成路由时,如果使用的数据集包含动态分段关系,则可能引起不必要的联动修改,导致之后的分析出现错误的结果。 因此建议不要直接使用包含动态分段关系的数据集 ,可以拷贝该数据集,或先删除该数据集的动态分段关系(需谨慎执行此步骤,因为一旦删除动态分段关系,该关系的三个角色间将不存在关联 ,不能再进行联动修改)。
- 建立了动态分段关系后,如果直接删除一个存在动态分段关系的数据集(路由数据集、事件表或空间数据),会抛出异常,必须先将其动态分段关系删除, 才能将该数据集删除。因此,建议在使用动态分段功能时,凡是进行删除数据集的操作,都先检查并删除或直接删除其动态分段关系。
通过该方法生成空间数据时,生成的结果是点数据还是线数据,由指定的参数决定。在生成空间数据参数设置(
GenerateSpatialDataParameter
)对象中,只要通过setMeasureField
方法指定了事件表中有效的刻度值字段,则生成的空间数据为点数据。因此,如果想要生成线数据,就需要指定有效的起始刻度字段和终至刻度字段 ,并且注意不能同时指定刻度值字段(setMeasureField)。生成空间数据涉及三个角色:路由数据集、事件表和空间数据。生成空间数据时,系统会建立并存储三者的动态分段关系,即根据路由 ID、刻度值字段等信息建立起三者的对应关系。动态分段关系主要用于实现三个角色间的联动修改。
如下图所示,在动态分段关系中,路由数据集与事件表为一对多的关系,路由数据集与空间数据为一对多的关系,事件表与空间数据为一对一的关系。也就是说, 路由数据集可以被多个事件表共用从而生成多个空间数据,但一个事件表只能对应一个空间数据。
SuperMap 提供了动态分段关系管理(
DynamicSegmentManager
)类,用于对动态分段关系进行检查和删除。生成空间数据之后,用于生成空间数据的路由数据集、事件表与生成的空间数据之间就建立了动态分段关系。有了该关系,在修改三者中的一个时,按照约定, 其他两者会自动发生相应的变化,SuperMap 称之为联动修改,是动态分段功能的重要特征。
目前,SuperMap 支持以下几种联动:
修改事件的描述信息,是指修改除路由标识字段和刻度字段之外的一般属性字段,如公路限速信息可能由于天气、施工等原因会做临时性修改。 如果修改事件表中的描述信息 ,从该事件表生成的空间数据的属性信息也会自动进行相应的修改。同样的,修改空间数据属性表中的一般属性字段时,其对应的事件表也会动态改变。
需要注意:如果修改后线事件的起始或终止 M 值超出了它所对应的路由的 M 值范围,则修改无效,对应的空间数据也不会发生变化。例如,修改事件表中某线事件的起始刻度和终止刻度为 18、60,而对应路由的 M 值范围为 3 到 20,则该条记录以及空间数据的几何信息都不会改变。
注意:如果修改路由数据集属性表中路由ID字段的值,该属性表可以修改成功,但对应的事件表和空间数据不会发生变化。
目前,不支持修改事件表表结构和增删表记录的联动,但提供
rebuildSpatialData
方法,用于对事件表的记录进行增删改等修改后,重新生成对应的空间数据。有关生成空间数据、动态分段关系和联动修改的内容,请阅读动态分段技术文档的 10 生成空间数据一章。
- 参数:
parameter
- 指定的生成空间数据参数设置。- 返回:
- 由事件表构建出来的空间数据。
- 示范代码:
- 示例一:以下代码示范了如何根据线事件表和路由数据集生成对应的线空间数据。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void GenerateSpatialDataExample() { // 获取用于生成空间数据的路由数据集 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector referenceLineM = (DatasetVector) datasource.getDatasets() .get("Roads_M"); // 获取用于生成空间数据的事件表数据集 // 避免破坏原始数据,所以复制一份数据,用于生成空间数据 if (datasource.getDatasets().contains("LineEventTab_1")) { datasource.getDatasets().delete("LineEventTab_1"); } DatasetVector eventTable = (DatasetVector) datasource.copyDataset( datasource.getDatasets().get("LineEventTab"), "LineEventTab_1", EncodeType.NONE); // 构造一个 GenerateSpatialDataParameter 对象并设置相关参数 GenerateSpatialDataParameter parameter = new GenerateSpatialDataParameter(); parameter.setEventTable(eventTable); parameter.setEventRouteIDField("ROUTEID"); parameter.setReferenceLineM(referenceLineM); parameter.setRouteIDField("ROUTEID"); parameter.setMeasureStartField("STARTMEASURE"); parameter.setMeasureEndField("ENDMEASURE"); parameter.setErrorInfoField("ERROR"); parameter.setOutputDatasetName("LineSpatialData"); if (datasource.getDatasets().contains("LineSpatialData")) { // 判断该数据集是否存在动态分段关系,如存在则删除关系 DatasetVector dynamicDataset = (DatasetVector) datasource .getDatasets().get("LineSpatialData"); DynamicSegmentInfo[] infos = DynamicSegmentManager .getDynamicSegmentInfos(dynamicDataset); if (infos.length != 0) { DynamicSegmentManager.removeDynamicSegmentInfos(dynamicDataset); } datasource.getDatasets().delete("LineSpatialData"); } // 调用 GenerateSpatialData 方法来生成空间数据 DatasetVector resultSpatialDataset = LinearReferencing .generateSpatialData(parameter); if (resultSpatialDataset != null) { JOptionPane.showMessageDialog(null, "生成空间数据成功!"); } //将路由和生成的空间数据加载到地图上 mapControl.getMap().getLayers().add(referenceLineM, false); mapControl.getMap().getLayers().add(resultSpatialDataset, true); mapControl.getMap().refresh(); }
, 示例二:以下代码示范了在生成空间数据之后,如何进行事件表与空间数据的联动修改。使用本示例代码,需要确保先使用示例一生成了空间数据(由事件表"LineEventTab_1"和路由数据集(Roads_M )生成空间数据(LineSpatialData)),并且相关数据集没有被删除,其所在数据源没有被关闭。
本示例中,通过修改事件表“LineEventTab_1”中的路况字段(BLOCK)的部分值,修改后,可观察对应的空间数据“ LineSpatialData”是否联动修改。
private void ModifyEventTableExample() { // 获取要修改的事件表,这里获取线事件表"LineEventTab_1" Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector eventTable = (DatasetVector) datasource.getDatasets().get( "LineEventTab_1"); // 获取该事件表的记录集 Recordset recordset = eventTable.query("BLOCK='M'", CursorType.DYNAMIC); // 将事件表中路况为“拥堵”的事件修改为“缓行”。字段值 M 表示拥堵,N 表示缓行。 recordset.moveFirst(); for (int i = 0; i < recordset.getRecordCount(); i++) { recordset.edit(); recordset.setFieldValue("BLOCK", "N"); recordset.update(); recordset.moveNext(); } recordset.close(); recordset.dispose(); // 加载线事件表对应的空间数据和路由到地图上 mapControl.getMap().getLayers().clear(); DatasetVector spatialData = (DatasetVector) datasource.getDatasets().get( "LineSpatialData"); DatasetVector referenceLineM = (DatasetVector) datasource.getDatasets() .get("Roads_M"); mapControl.getMap().getLayers().add(spatialData, false); mapControl.getMap().getLayers().add(referenceLineM, false); mapControl.getMap().refresh(); }
-
generateSpatialData
public static DatasetVector generateSpatialData(GenerateSpatialDataParameter parameter, SteppedListener... listeners)
根据点或线事件表生成空间数据。成功则返回定位后的点或者线数据集,如果是线事件表,生成的是路由数据集。事件表用属性表的方式记录了点或者线事件发生所在的路由、刻度、事件的描述信息(如交通事故发生地的天气状况、驾驶者的酒精含量、当时的车速、路面宽度、 铺设材料等 )。如下图所示,生成空间数据就是根据路由数据集,将事件表中的事件定位到空间上,生成相应的点或者线数据,并建立和存储三者间的动态分段关系的过程 。其中点事件对应生成点数据集 ,线事件表对应生成的线数据为路由数据集。动态分段关系隐含存储在数据集中,记录了路由数据集、事件表与生成的空间数据三者间的对应关系 ,是进行联动修改(即修改三者中的一个,其他两个根据规则自动进行修改)也就是动态分段的依据。
- 生成的空间数据的类型
- 动态分段关系
- 路由、事件表和空间数据的联动
- 事件的描述信息发生变化。这种情况在事件表与空间数据之间发生联动。
-
事件发生的路由位置发生变化。这种情况在事件表与空间数据之间发生动态变化。
修改事件发生的位置,是指修改事件表或空间数据中的刻度值字段。如果修改事件表中某条记录(事件)的刻度值, 那么对应的空间数据中该事件对应的点或者线对象的几何信息和属性表中对应记录的刻度字段也会做相应修改 ;如果修改生成的空间数据的属性表中的刻度字段的值,对应的对象的几何信息也会修改 ,事件表中的相关联的事件的刻度字段的值也会动态发生同等变化。如果是线事件 ,可以修改起始刻度或者终止刻度,事件的长度和位置可能发生变化。如下图所示,是生成空间数据之后 ,将对应事件表中第一条事件的起始刻度和终止刻度由(20.78 ,79.37)修改为(150.00,180.00)前后,对应空间数据中对应该事件的线的变化 ,可以看出,当事件的刻度值发生变化后,对应的空间数据也自动进行对应的修改。
-
事件发生的路由改变。这种情况下,空间数据会根据路由数据集的修改发生变化,而修改空间数据时,对应的路由数据不会发生变化; 事件表与空间数据之间会发生联动修改。
这种情况适用于由于数据错误或者变更导致事件所发生的路由需要修改的情形,具体分为以下三种情形:
- 如果修改的是路由对象的空间几何信息,对应的空间数据中相关对象的几何信息也会自动修改。如果发生事件的路由的位置和刻度值发生变化, 如管道维修后走向发生了变化,它的形状和刻度值可能都需要修改。这时就需要对路由对象本身的空间几何信息进行修改,如旋转、移动,修改刻度值等。修改后, 对应的空间数据中相关对象的几何信息会作相应的变化,即对应的事件和空间数据将重新定位。
- 如果修改的是事件表的中某记录的路由 ID,则空间数据中与之关联的对象的几何信息和属性表中的路由ID字段也会随之动态改变。如下图中的事件表及其对应的空间数据,将事件表中第一条记录的路由 ID 由1改为2之后,该记录对应的空间数据也发生了变化,被定位到了 ID 为2的路由上面,正如下图(下)所展示的一样。
- 如果修改的是生成的空间数据的路由 ID,则事件表中对应记录的路由 ID 值也会改变,同时,空间数据的几何信息也会根据修改后对应的路由而进行修改。
- 注意:
- 用于生成空间数据的事件表中必须包含路由标识字段和刻度字段(点事件包含刻度字段,线事件包含起始刻度字段和终止刻度字段)。 路由标识字段的值用于将事件对应的点或线定位到正确的路由上 ,刻度字段的值使事件对应的点或线最终正确定位。事件表中的路由标识字段、刻度字段及其他描述事件的属性,都会写入生成的空间数据的属性表中。
- 通过该方法生成空间数据时,系统会在结果数据集中添加一个名为“Event_SMID”的字段,用于存储事件表中对应事件的 SMID。特别需要注意的是,不能修改该字段,否则可能导致联动的结果错误。
- 由于事件表与空间数据为一对一关系,如果某事件表已经具有了一个动态分段关系,则不能再次用于其他的生成空间数据,除非将其关系删除。因此,在调用
GenerateSpatialData 方法生成空间数据前,应先使用
DynamicSegmentManager
类的 getDynamicSegmentInfos 方法检查事件表是否存在动态分段关系,如果存在则调用 removeDynamicSegmentInfos 方法删除关系。但请注意,可以使用rebuildSpatialData
方法重新生成同名的空间数据,此时不必删除动态分段关系。 - 校准、事件表融合、线参考点刻度生成路由时,如果使用的数据集包含动态分段关系,则可能引起不必要的联动修改,导致之后的分析出现错误的结果。 因此建议不要直接使用包含动态分段关系的数据集 ,可以拷贝该数据集,或先删除该数据集的动态分段关系(需谨慎执行此步骤,因为一旦删除动态分段关系,该关系的三个角色间将不存在关联 ,不能再进行联动修改)。
- 建立了动态分段关系后,如果直接删除一个存在动态分段关系的数据集(路由数据集、事件表或空间数据),会抛出异常,必须先将其动态分段关系删除, 才能将该数据集删除。因此,建议在使用动态分段功能时,凡是进行删除数据集的操作,都先检查并删除或直接删除其动态分段关系。
通过该方法生成空间数据时,生成的结果是点数据还是线数据,由指定的参数决定。在生成空间数据参数设置(
GenerateSpatialDataParameter
)对象中,只要通过setMeasureField
方法指定了事件表中有效的刻度值字段,则生成的空间数据为点数据。因此,如果想要生成线数据,就需要指定有效的起始刻度字段和终至刻度字段 ,并且注意不能同时指定刻度值字段(setMeasureField)。生成空间数据涉及三个角色:路由数据集、事件表和空间数据。生成空间数据时,系统会建立并存储三者的动态分段关系,即根据路由 ID、刻度值字段等信息建立起三者的对应关系。动态分段关系主要用于实现三个角色间的联动修改。
如下图所示,在动态分段关系中,路由数据集与事件表为一对多的关系,路由数据集与空间数据为一对多的关系,事件表与空间数据为一对一的关系。也就是说, 路由数据集可以被多个事件表共用从而生成多个空间数据,但一个事件表只能对应一个空间数据。
SuperMap 提供了动态分段关系管理(
DynamicSegmentManager
)类,用于对动态分段关系进行检查和删除。生成空间数据之后,用于生成空间数据的路由数据集、事件表与生成的空间数据之间就建立了动态分段关系。有了该关系,在修改三者中的一个时,按照约定, 其他两者会自动发生相应的变化,SuperMap 称之为联动修改,是动态分段功能的重要特征。
目前,SuperMap 支持以下几种联动:
修改事件的描述信息,是指修改除路由标识字段和刻度字段之外的一般属性字段,如公路限速信息可能由于天气、施工等原因会做临时性修改。 如果修改事件表中的描述信息 ,从该事件表生成的空间数据的属性信息也会自动进行相应的修改。同样的,修改空间数据属性表中的一般属性字段时,其对应的事件表也会动态改变。
需要注意:如果修改后线事件的起始或终止 M 值超出了它所对应的路由的 M 值范围,则修改无效,对应的空间数据也不会发生变化。例如,修改事件表中某线事件的起始刻度和终止刻度为 18、60,而对应路由的 M 值范围为 3 到 20,则该条记录以及空间数据的几何信息都不会改变。
注意:如果修改路由数据集属性表中路由ID字段的值,该属性表可以修改成功,但对应的事件表和空间数据不会发生变化。
目前,不支持修改事件表表结构和增删表记录的联动,但提供
rebuildSpatialData
方法,用于对事件表的记录进行增删改等修改后,重新生成对应的空间数据。有关生成空间数据、动态分段关系和联动修改的内容,请阅读动态分段技术文档的 10 生成空间数据一章。
- 参数:
parameter
- 指定的生成空间数据参数设置。listeners
- 用于接收进度条事件的监听器。- 返回:
- 由事件表构建出来的空间数据。
- 示范代码:
- 示例一:以下代码示范了如何根据线事件表和路由数据集生成对应的线空间数据。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void GenerateSpatialDataExample() { // 获取用于生成空间数据的路由数据集 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector referenceLineM = (DatasetVector) datasource.getDatasets() .get("Roads_M"); // 获取用于生成空间数据的事件表数据集 // 避免破坏原始数据,所以复制一份数据,用于生成空间数据 if (datasource.getDatasets().contains("LineEventTab_1")) { datasource.getDatasets().delete("LineEventTab_1"); } DatasetVector eventTable = (DatasetVector) datasource.copyDataset( datasource.getDatasets().get("LineEventTab"), "LineEventTab_1", EncodeType.NONE); // 构造一个 GenerateSpatialDataParameter 对象并设置相关参数 GenerateSpatialDataParameter parameter = new GenerateSpatialDataParameter(); parameter.setEventTable(eventTable); parameter.setEventRouteIDField("ROUTEID"); parameter.setReferenceLineM(referenceLineM); parameter.setRouteIDField("ROUTEID"); parameter.setMeasureStartField("STARTMEASURE"); parameter.setMeasureEndField("ENDMEASURE"); parameter.setErrorInfoField("ERROR"); parameter.setOutputDatasetName("LineSpatialData"); if (datasource.getDatasets().contains("LineSpatialData")) { // 判断该数据集是否存在动态分段关系,如存在则删除关系 DatasetVector dynamicDataset = (DatasetVector) datasource .getDatasets().get("LineSpatialData"); DynamicSegmentInfo[] infos = DynamicSegmentManager .getDynamicSegmentInfos(dynamicDataset); if (infos.length != 0) { DynamicSegmentManager.removeDynamicSegmentInfos(dynamicDataset); } datasource.getDatasets().delete("LineSpatialData"); } // 调用 GenerateSpatialData 方法来生成空间数据 DatasetVector resultSpatialDataset = LinearReferencing .generateSpatialData(parameter); if (resultSpatialDataset != null) { JOptionPane.showMessageDialog(null, "生成空间数据成功!"); } //将路由和生成的空间数据加载到地图上 mapControl.getMap().getLayers().add(referenceLineM, false); mapControl.getMap().getLayers().add(resultSpatialDataset, true); mapControl.getMap().refresh(); }
, 示例二:以下代码示范了在生成空间数据之后,如何进行事件表与空间数据的联动修改。使用本示例代码,需要确保先使用示例一生成了空间数据(由事件表"LineEventTab_1"和路由数据集(Roads_M )生成空间数据(LineSpatialData)),并且相关数据集没有被删除,其所在数据源没有被关闭。
本示例中,通过修改事件表“LineEventTab_1”中的路况字段(BLOCK)的部分值,修改后,可观察对应的空间数据“ LineSpatialData”是否联动修改。
private void ModifyEventTableExample() { // 获取要修改的事件表,这里获取线事件表"LineEventTab_1" Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector eventTable = (DatasetVector) datasource.getDatasets().get( "LineEventTab_1"); // 获取该事件表的记录集 Recordset recordset = eventTable.query("BLOCK='M'", CursorType.DYNAMIC); // 将事件表中路况为“拥堵”的事件修改为“缓行”。字段值 M 表示拥堵,N 表示缓行。 recordset.moveFirst(); for (int i = 0; i < recordset.getRecordCount(); i++) { recordset.edit(); recordset.setFieldValue("BLOCK", "N"); recordset.update(); recordset.moveNext(); } recordset.close(); recordset.dispose(); // 加载线事件表对应的空间数据和路由到地图上 mapControl.getMap().getLayers().clear(); DatasetVector spatialData = (DatasetVector) datasource.getDatasets().get( "LineSpatialData"); DatasetVector referenceLineM = (DatasetVector) datasource.getDatasets() .get("Roads_M"); mapControl.getMap().getLayers().add(spatialData, false); mapControl.getMap().getLayers().add(referenceLineM, false); mapControl.getMap().refresh(); }
-
dissolveRouteEvents
@Deprecated public static DatasetVector dissolveRouteEvents(RouteEventsParameter inputEventsParameter, String[] dissolveFields, EventDissolveType eventDissolveType, Datasource outputDatasource, String outputDatasetName, RouteEventsParameter resultEventsParameter, String[] statisticFields, StatisticsType[] statisticModes, double tolerance)
已过时。 此方法已废弃,请使用支持进度监听的新方法LinearReferencing.dissolveRouteEvents(RouteEventsParameter, String[], EventDissolveType, Datasource, String, RouteEventsParameter, String[], StatisticsType[], double, SteppedListener...)
替换。融合事件表。用于将冗余信息从事件表中移除,或将包含多个描述性属性的事件表分解为单独的事件表。- 什么是融合事件表?
- 使用事件表融合去除冗余数据。
- 使用事件表融合拆分事件表。
- 融合事件表的方式
- 连接:将两个具有相同路由 ID 和融合字段值,并且首尾相连的事件合并为一个事件写入结果事件表中。
- 交叠:将两个具有相同路由 ID 和融合字段值的事件的交叠部分作为结果事件写入结果事件表中。
- 说明:
- 调用该方法时,需要分别对输入事件和结果事件的参数进行设置,因此需要构造两个
RouteEventsParameter
对象并设置其对应的属性。 - 方法中的 dissolveFields 参数用于指定一个或多个融合字段。只有融合字段值相同的同一条路由上的两个事件才可能被融合。如果设置多个融合字段 ,则要求两事件所有融合字段的值均对应相同 。如将城市道路交通状况的事件表中,存储了拥堵状况信息的字段作为融合字段,可以将一条道路上拥堵状态相同(如均为通畅)的路段进行融合。
- 事件融合可能使两个或者多个事件被连接或者取交叠部分,生成一个新的事件。而这些输入事件的某些属性字段的值可能不同,通过
statisticFields 参数可以指定这些字段,并通过一定的统计方法(statisticModes 参数)取值。统计方法由
StatisticsType
类型定义 ,有取最大值(Max)、最小值(Min)、取和(Sum)、取平均值(Mean)、取第一个值(First)和取最后一个值(Last)等方法 。注意,统计字段集合与统计方法集合是按照数组元素索引值按顺序对应的。 - 该方法中的 tolerance 参数允许用户设置一个值,称为“融合容限”,当事件之间的刻度小于该值时,两个事件将被融合。融合容限的度量单位与进行融合的事件表的刻度值的一致。
事件表的融合是指对一个事件表进行的操作,将具有相同路由 ID 和融合字段值(该值用于标识哪些事件可以融合,具有相同融合字段值的事件才能融合)按照一定方式进行合并 ,可以达到去除冗余信息或依据不同属性信息对事件表进行拆分的目的。
如下图所示,在一份高速公路限速事件表中,使用 Speed 字段记录了不同路段的最高限速值,其中相邻的路段可能限速相同,但却使用了两个事件来表示,造成了数据的冗余 。这时就可以通过连接的方式对事件表进行融合以去除冗余的事件。同样,如果这些事件在位置上有交叠,也可通过交叠的方式融合来去除多余的数据。
事件表中可能使用多个属性字段记录了事件的多个特性,通过指定不同的融合字段,对事件表进行多次融合,可以将一个事件表按照不同描述属性拆分为多个事件表。 如下图所示,在一份交通状况事件表中,分别使用 Block 和 Lane 字段记录了不同路段的路宽和某一时刻的道路拥堵状况。可以分别指定 Block 和 Lane 字段为融合字段,对该事件表进行两次融合,可以将其拆分出两个事件表,一个描述某时刻道路的拥堵状况,一个记录了道路的宽度。
事件表的融合有两种方式,由
EventDissolveType
类型定义,分别是连接(EventConcatenate)和交叠(EventOverlap)。事件表的融合支持线事件融合和点事件表融合。可以结合下面两幅图来帮助理解事件表的连接和交叠。示意图中事件具有相同的路由ID, 线事件或点事件的标号代表其融合字段的值,从图中可看出,融合字段相同的事件才被融合。
从图中可以看出,对点事件表融合时,无论是连接还是交叠,其融合的结果都是一样的。
- 参数:
inputEventsParameter
- 指定的输入事件参数设置。dissolveFields
- 指定的融合字段集合。只有这些属性值相同的事件才会被融合。支持除 LONGBINARY(二进制)以外的所有字段类型(FieldType
)。eventDissolveType
- 指定的事件融合类型。outputDatasource
- 指定的用于存储结果事件表的数据源。如果设为 null,则将结果事件表输出到输入数事件所在的数据源。outputDatasetName
- 指定的结果数据集的名称。resultEventsParameter
- 指定的融合结果事件参数设置。statisticFields
- 指定的统计字段集合,即事件表融合之后,除融合的参照字段外,需进行重新取值的字段。指定为一个零长度数组表示不对任何字段进行统计。只支持数值型的字段。statisticModes
- 指定的统计字段类型集合。tolerance
- 指定的融合容限。单位与进行融合的事件表的刻度值单位相同。- 返回:
- 一个数据集,即融合结果数据集,融合失败则返回 null。
- 示范代码:
- 以下代码示范了如何进行事件表的融合。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void EventTableDissolveExample() { // 获取要融合的事件表,这里获取一个线事件表 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector eventTable = (DatasetVector) datasource.getDatasets().get( "LineEventTab"); // 构造一个 RouteEventsParameter 对象并设置输入事件参数 RouteEventsParameter inputParameter = new RouteEventsParameter(); inputParameter.setEventDataset(eventTable); inputParameter.setRouteIDField("RouteID"); inputParameter.setMeasureStartField("StartMeasure"); inputParameter.setMeasureEndField("EndMeasure"); // 构造一个 RouteEventsParameter 对象并设置融合结果参数 RouteEventsParameter resultParameter = new RouteEventsParameter(); resultParameter.setRouteIDField("RouteID"); resultParameter.setMeasureStartField("StartMeasure"); resultParameter.setMeasureEndField("EndMeasure"); // 指定事件表中的融合字段 String[] dissolveFields = { "RATING" }; // 指定事件表中的统计字段及统计方法 String[] statisticsFields = { "ADT" }; StatisticsType[] statisticsModes = { StatisticsType.MEAN }; String outputDatasetName = "DissolvedTab"; if (datasource.getDatasets().contains("DissolvedTab")) { // 判断该数据集是否存在动态分段关系,如存在则删除关系 DatasetVector dynamicDataset = (DatasetVector) datasource .getDatasets().get("DissolvedTab"); DynamicSegmentInfo[] infos = DynamicSegmentManager .getDynamicSegmentInfos(dynamicDataset); if (infos.length != 0) { DynamicSegmentManager.removeDynamicSegmentInfos(dynamicDataset); } datasource.getDatasets().delete("DissolvedTab"); } // 调用 DissolveRouteEvents 方法实现事件表的融合,融合类型设置为”连接“ DatasetVector resultDissolveTable = LinearReferencing.dissolveRouteEvents( inputParameter, dissolveFields, EventDissolveType.EVENT_CONCATENATE, datasource, outputDatasetName, resultParameter, statisticsFields, statisticsModes, 0.001); if (resultDissolveTable != null) { JOptionPane.showMessageDialog(null, "融合成功!"); } }
-
dissolveRouteEvents
public static DatasetVector dissolveRouteEvents(RouteEventsParameter inputEventsParameter, String[] dissolveFields, EventDissolveType eventDissolveType, Datasource outputDatasource, String outputDatasetName, RouteEventsParameter resultEventsParameter, String[] statisticFields, StatisticsType[] statisticModes, double tolerance, SteppedListener... listeners)
融合事件表。用于将冗余信息从事件表中移除,或将包含多个描述性属性的事件表分解为单独的事件表。- 什么是融合事件表?
- 使用事件表融合去除冗余数据。
- 使用事件表融合拆分事件表。
- 融合事件表的方式
- 连接:将两个具有相同路由 ID 和融合字段值,并且首尾相连的事件合并为一个事件写入结果事件表中。
- 交叠:将两个具有相同路由 ID 和融合字段值的事件的交叠部分作为结果事件写入结果事件表中。
- 说明:
- 调用该方法时,需要分别对输入事件和结果事件的参数进行设置,因此需要构造两个
RouteEventsParameter
对象并设置其对应的属性。 - 方法中的 dissolveFields 参数用于指定一个或多个融合字段。只有融合字段值相同的同一条路由上的两个事件才可能被融合。如果设置多个融合字段 ,则要求两事件所有融合字段的值均对应相同 。如将城市道路交通状况的事件表中,存储了拥堵状况信息的字段作为融合字段,可以将一条道路上拥堵状态相同(如均为通畅)的路段进行融合。
- 事件融合可能使两个或者多个事件被连接或者取交叠部分,生成一个新的事件。而这些输入事件的某些属性字段的值可能不同,通过
statisticFields 参数可以指定这些字段,并通过一定的统计方法(statisticModes 参数)取值。统计方法由
StatisticsType
类型定义 ,有取最大值(Max)、最小值(Min)、取和(Sum)、取平均值(Mean)、取第一个值(First)和取最后一个值(Last)等方法 。注意,统计字段集合与统计方法集合是按照数组元素索引值按顺序对应的。 - 该方法中的 tolerance 参数允许用户设置一个值,称为“融合容限”,当事件之间的刻度小于该值时,两个事件将被融合。融合容限的度量单位与进行融合的事件表的刻度值的一致。
事件表的融合是指对一个事件表进行的操作,将具有相同路由 ID 和融合字段值(该值用于标识哪些事件可以融合,具有相同融合字段值的事件才能融合)按照一定方式进行合并 ,可以达到去除冗余信息或依据不同属性信息对事件表进行拆分的目的。
如下图所示,在一份高速公路限速事件表中,使用 Speed 字段记录了不同路段的最高限速值,其中相邻的路段可能限速相同,但却使用了两个事件来表示,造成了数据的冗余 。这时就可以通过连接的方式对事件表进行融合以去除冗余的事件。同样,如果这些事件在位置上有交叠,也可通过交叠的方式融合来去除多余的数据。
事件表中可能使用多个属性字段记录了事件的多个特性,通过指定不同的融合字段,对事件表进行多次融合,可以将一个事件表按照不同描述属性拆分为多个事件表。 如下图所示,在一份交通状况事件表中,分别使用 Block 和 Lane 字段记录了不同路段的路宽和某一时刻的道路拥堵状况。可以分别指定 Block 和 Lane 字段为融合字段,对该事件表进行两次融合,可以将其拆分出两个事件表,一个描述某时刻道路的拥堵状况,一个记录了道路的宽度。
事件表的融合有两种方式,由
EventDissolveType
类型定义,分别是连接(EventConcatenate)和交叠(EventOverlap)。事件表的融合支持线事件融合和点事件表融合。可以结合下面两幅图来帮助理解事件表的连接和交叠。示意图中事件具有相同的路由ID, 线事件或点事件的标号代表其融合字段的值,从图中可看出,融合字段相同的事件才被融合。
从图中可以看出,对点事件表融合时,无论是连接还是交叠,其融合的结果都是一样的。
- 参数:
inputEventsParameter
- 指定的输入事件参数设置。dissolveFields
- 指定的融合字段集合。只有这些属性值相同的事件才会被融合。支持除 LONGBINARY(二进制)以外的所有字段类型(FieldType
)。eventDissolveType
- 指定的事件融合类型。outputDatasource
- 指定的用于存储结果事件表的数据源。如果设为 null,则将结果事件表输出到输入数事件所在的数据源。outputDatasetName
- 指定的结果数据集的名称。resultEventsParameter
- 指定的融合结果事件参数设置。statisticFields
- 指定的统计字段集合,即事件表融合之后,除融合的参照字段外,需进行重新取值的字段。指定为一个零长度数组表示不对任何字段进行统计。只支持数值型的字段。statisticModes
- 指定的统计字段类型集合。tolerance
- 指定的融合容限。单位与进行融合的事件表的刻度值单位相同。listeners
- 用于接收进度条事件的监听器。- 返回:
- 一个数据集,即融合结果数据集,融合失败则返回 null。
- 示范代码:
- 以下代码示范了如何进行事件表的融合。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void EventTableDissolveExample() { // 获取要融合的事件表,这里获取一个线事件表 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector eventTable = (DatasetVector) datasource.getDatasets().get( "LineEventTab"); // 构造一个 RouteEventsParameter 对象并设置输入事件参数 RouteEventsParameter inputParameter = new RouteEventsParameter(); inputParameter.setEventDataset(eventTable); inputParameter.setRouteIDField("RouteID"); inputParameter.setMeasureStartField("StartMeasure"); inputParameter.setMeasureEndField("EndMeasure"); // 构造一个 RouteEventsParameter 对象并设置融合结果参数 RouteEventsParameter resultParameter = new RouteEventsParameter(); resultParameter.setRouteIDField("RouteID"); resultParameter.setMeasureStartField("StartMeasure"); resultParameter.setMeasureEndField("EndMeasure"); // 指定事件表中的融合字段 String[] dissolveFields = { "RATING" }; // 指定事件表中的统计字段及统计方法 String[] statisticsFields = { "ADT" }; StatisticsType[] statisticsModes = { StatisticsType.MEAN }; String outputDatasetName = "DissolvedTab"; if (datasource.getDatasets().contains("DissolvedTab")) { // 判断该数据集是否存在动态分段关系,如存在则删除关系 DatasetVector dynamicDataset = (DatasetVector) datasource .getDatasets().get("DissolvedTab"); DynamicSegmentInfo[] infos = DynamicSegmentManager .getDynamicSegmentInfos(dynamicDataset); if (infos.length != 0) { DynamicSegmentManager.removeDynamicSegmentInfos(dynamicDataset); } datasource.getDatasets().delete("DissolvedTab"); } // 调用 DissolveRouteEvents 方法实现事件表的融合,融合类型设置为”连接“ DatasetVector resultDissolveTable = LinearReferencing.dissolveRouteEvents( inputParameter, dissolveFields, EventDissolveType.EVENT_CONCATENATE, datasource, outputDatasetName, resultParameter, statisticsFields, statisticsModes, 0.001); if (resultDissolveTable != null) { JOptionPane.showMessageDialog(null, "融合成功!"); } }
-
overlayRouteEvents
@Deprecated public static DatasetVector overlayRouteEvents(RouteEventsParameter inputEventsParameter, RouteEventsParameter overlayEventParameter, EventOverlayType eventOverlayType, Datasource outputDatasource, String outputDatasetName, RouteEventsParameter resultEventsParameter, double tolerance, boolean isKeepField, boolean isKeepZeroLengthEvents)
已过时。 此方法已废弃,请使用支持进度监听的新方法LinearReferencing.overlayRouteEvents(RouteEventsParameter, RouteEventsParameter, EventOverlayType, Datasource, String, RouteEventsParameter, double, boolean, boolean, SteppedListener...)
替换。叠加事件表。用于将两个事件表叠加起来创建一个输出事件表,以表示输入的并集或交集。- 什么是叠加事件表?
- 叠加事件表的方式
- 事件求交集:事件求交集的叠加方式会将具有相同路由 ID 的事件的交叠的部分输出到结果事件表中。
- 事件求并集:事件求并集的叠加方式较为复杂,首先计算出事件的交集,这部分将写入结果事件表中,然后使用交集对所有事件(包括输入和叠加事件)进行分割 ,将处于交集范围外的事件写入结果事件表中(可结合“叠加类型”部分中的图示来帮助理解)。
- 线线叠加
- 点线(线点)叠加
- 点点叠加
- 说明
- 调用该方法时,需要分别对输入事件、叠加事件和结果事件的参数进行设置,因此需要构造三个
RouteEventsParameter
对象并设置其对应的属性。 - 该方法中的 tolerance 参数所指定的容限值用于判断叠加结果产生的线事件是否为零长度事件。如果结果线事件的起始刻度和终止刻度的差的绝对值小于设置的容限 ,就认为它是零长度事件。
- 如果设置 isKeepField 参数为 true,则输入事件和叠加事件表中除系统字段、路由标识字段和刻度字段之外的属性字段会写入到结果事件表中 ,并分别在原字段名后加“_in”和“_over”来命名,字段值将根据结果事件是由哪个输入事件和叠加事件生成来确定。
- 输入事件表和叠加事件表中的刻度字段记录了事件发生的刻度值,刻度值的单位与事件表数据的来源有关,可能不相同。但在进行事件表叠加时, 二者的单位应该统一,例如,描述高速公路上发生的事件的两个事件表中,分别有表示里程的刻度字段,它们的度量单位应一致,如都是千米或者英里,如果不一致, 需要使用者对数据进行处理,否则分析的结果可能不正确。用于判断零长度事件的容限的单位与事件表的刻度值单位一致。
- 导致叠加失败的可能的原因
- 事件表参数没有被正确设置。例如,点事件的刻度字段为空。
- 只读打开数据源。该方法会在结果数据源中创建数据集,需要数据源可写。
- 字段非法。例如,路由标识字段的类型为 Text。
事件表的叠加需要输入两个事件表,将第一个事件表中的所有事件(称为输入事件)分别与第二个事件表中的所有事件(称为叠加事件)进行求交或求并的操作, 结果会生成一个新的事件表。叠加的前提是输入事件和叠加事件具有相同的路由 ID,也就是说,具有相同路由 ID 的输入事件和叠加事件进行叠加才能产生结果。
对事件表叠加的结果事件表进行分析,可以帮助我们解决一些传统空间分析技术不能解决的问题。例如,在一份交通事故数据中, 有两个事件表分别记录了事故发生时的路面宽度 (Lane)和车速(Speed),将这两个事件表进行叠加求交,结果事件表中则是同时记录了路宽和车速两个信息的交通事故事件 。从结果事件表中,可以快速获知交通事故的综合信息 ,如发生在路面宽度小于10米,且事故发生时车速大于70km/h的交通事故有哪些。如果是叠加求并,则可用于查找路面宽度小于10米 ,或车速大于70,以及宽度小于10米且车速大于70的交通事故事件。
事件表的叠加有两种方式,由
EventOverlayType
类定义,分别是事件求交集(EventIntersect)和事件求并集(EventUnion)。事件表的叠加支持线线叠加(两个线事件表进行叠加),点线(线点)叠加(一个点事件与一个线事件叠加)和点点叠加(两个点事件叠加)。
线线叠加的结果为一个新的线事件表。下图为线线叠加的示意图,在这里输入事件与叠加事件具有相同的路由 ID。需要注意,一个输入线事件与一个叠加线事件成首尾相连状态时(如下图中的事件a与A),会产生一个零长度事件。
点事件表与线事件表以求交方式叠加产生一个新的点事件表,而使用求并方式叠加产生一个新的线事件表。点线叠加与线点叠加的结果事件表类型相同。 下图为一个点事件表和一个线事件表叠加的示意图。采用求并方式叠加时,点事件处和点事件与线事件的相交处会产生零长度事件,比如图中的点事件2与线事件 a 叠加产生零长度事件 2a。
两个点事件表叠加的结果为一个点事件表。由于其分析的意义不大,因此在实际应用中较少用到。用户可根据实际研究的需要来使用,在此不做赘述。
- 参数:
inputEventsParameter
- 指定的输入事件参数设置。overlayEventParameter
- 指定的叠加事件参数设置。eventOverlayType
- 指定的事件叠加类型。outputDatasource
- 指定的用于存储结果事件表的数据源。如果设为 null,则将结果事件表输出到输入事件所在的数据源。outputDatasetName
- 指定的结果数据集的名称。resultEventsParameter
- 指定的叠加结果事件参数设置。tolerance
- 指定的叠加容限。单位与结果事件表的刻度值单位相同。isKeepField
- 指定是否保留属性字段。如果为 true 则会将输入事件表和叠加事件表中除系统字段外的属性字段写入结果事件表,名称以“_in”结尾的字段表示来自输入事件表,以“_over”结尾的字段表示来自叠加事件表;指定为 false 则不写入。isKeepZeroLengthEvents
- 指定是否保留零长度线事件。如果为 true,则叠加产生的零长度事件会写入结果事件表中,false 则不会写入。- 返回:
- 叠加结果数据集;叠加失败则返回 null。
- 示范代码:
- 以下代码示范了如何进行事件表的叠加。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void EventTableOverlayExample() { // 获取进行叠加的两个事件表,这里获取一个点事件表和一个线事件表 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector eventTablePoint = (DatasetVector) datasource.getDatasets() .get("PointEventTab"); DatasetVector eventTableLine = (DatasetVector) datasource.getDatasets() .get("LineEventTab"); // 构造一个 RouteEventsParameter 对象并设置输入事件参数 RouteEventsParameter inputEventParameter = new RouteEventsParameter(); inputEventParameter.setEventDataset(eventTablePoint); inputEventParameter.setRouteIDField("ROUTEID"); inputEventParameter.setMeasureField("MEASURE"); // 构造一个 RouteEventsParameter 对象并设置叠加事件参数 RouteEventsParameter overlayEventParameter = new RouteEventsParameter(); overlayEventParameter.setEventDataset(eventTableLine); overlayEventParameter.setRouteIDField("ROUTEID"); overlayEventParameter.setMeasureStartField("STARTMEASURE"); overlayEventParameter.setMeasureEndField("ENDMEASURE"); // 构造一个 RouteEventsParameter 对象并设置结果事件参数 RouteEventsParameter resultEventParameter = new RouteEventsParameter(); resultEventParameter.setRouteIDField("ROUTEID"); resultEventParameter.setMeasureField("MEASURE"); resultEventParameter.setMeasureStartField("STARTMEASURE"); resultEventParameter.setMeasureEndField("ENDMEASURE"); // 调用 OverlayRouteEvents 方法实现事件表的叠加,叠加类型设置为”求交“ DatasetVector resultOverlayEventTable = LinearReferencing .overlayRouteEvents(inputEventParameter, overlayEventParameter, EventOverlayType.EVENT_INTERSECT, datasource, "EventOverlayResult", resultEventParameter, 0.0, true, false); if (resultOverlayEventTable != null) { JOptionPane.showMessageDialog(null, "事件表叠加成功!"); } }
-
overlayRouteEvents
public static DatasetVector overlayRouteEvents(RouteEventsParameter inputEventsParameter, RouteEventsParameter overlayEventParameter, EventOverlayType eventOverlayType, Datasource outputDatasource, String outputDatasetName, RouteEventsParameter resultEventsParameter, double tolerance, boolean isKeepField, boolean isKeepZeroLengthEvents, SteppedListener... listeners)
叠加事件表。用于将两个事件表叠加起来创建一个输出事件表,以表示输入的并集或交集。- 什么是叠加事件表?
- 叠加事件表的方式
- 事件求交集:事件求交集的叠加方式会将具有相同路由 ID 的事件的交叠的部分输出到结果事件表中。
- 事件求并集:事件求并集的叠加方式较为复杂,首先计算出事件的交集,这部分将写入结果事件表中,然后使用交集对所有事件(包括输入和叠加事件)进行分割 ,将处于交集范围外的事件写入结果事件表中(可结合“叠加类型”部分中的图示来帮助理解)。
- 线线叠加
- 点线(线点)叠加
- 点点叠加
- 说明
- 调用该方法时,需要分别对输入事件、叠加事件和结果事件的参数进行设置,因此需要构造三个
RouteEventsParameter
对象并设置其对应的属性。 - 该方法中的 tolerance 参数所指定的容限值用于判断叠加结果产生的线事件是否为零长度事件。如果结果线事件的起始刻度和终止刻度的差的绝对值小于设置的容限 ,就认为它是零长度事件。
- 如果设置 isKeepField 参数为 true,则输入事件和叠加事件表中除系统字段、路由标识字段和刻度字段之外的属性字段会写入到结果事件表中 ,并分别在原字段名后加“_in”和“_over”来命名,字段值将根据结果事件是由哪个输入事件和叠加事件生成来确定。
- 输入事件表和叠加事件表中的刻度字段记录了事件发生的刻度值,刻度值的单位与事件表数据的来源有关,可能不相同。但在进行事件表叠加时, 二者的单位应该统一,例如,描述高速公路上发生的事件的两个事件表中,分别有表示里程的刻度字段,它们的度量单位应一致,如都是千米或者英里,如果不一致, 需要使用者对数据进行处理,否则分析的结果可能不正确。用于判断零长度事件的容限的单位与事件表的刻度值单位一致。
- 导致叠加失败的可能的原因
- 事件表参数没有被正确设置。例如,点事件的刻度字段为空。
- 只读打开数据源。该方法会在结果数据源中创建数据集,需要数据源可写。
- 字段非法。例如,路由标识字段的类型为 Text。
事件表的叠加需要输入两个事件表,将第一个事件表中的所有事件(称为输入事件)分别与第二个事件表中的所有事件(称为叠加事件)进行求交或求并的操作, 结果会生成一个新的事件表。叠加的前提是输入事件和叠加事件具有相同的路由 ID,也就是说,具有相同路由 ID 的输入事件和叠加事件进行叠加才能产生结果。
对事件表叠加的结果事件表进行分析,可以帮助我们解决一些传统空间分析技术不能解决的问题。例如,在一份交通事故数据中, 有两个事件表分别记录了事故发生时的路面宽度 (Lane)和车速(Speed),将这两个事件表进行叠加求交,结果事件表中则是同时记录了路宽和车速两个信息的交通事故事件 。从结果事件表中,可以快速获知交通事故的综合信息 ,如发生在路面宽度小于10米,且事故发生时车速大于70km/h的交通事故有哪些。如果是叠加求并,则可用于查找路面宽度小于10米 ,或车速大于70,以及宽度小于10米且车速大于70的交通事故事件。
事件表的叠加有两种方式,由
EventOverlayType
类定义,分别是事件求交集(EventIntersect)和事件求并集(EventUnion)。事件表的叠加支持线线叠加(两个线事件表进行叠加),点线(线点)叠加(一个点事件与一个线事件叠加)和点点叠加(两个点事件叠加)。
线线叠加的结果为一个新的线事件表。下图为线线叠加的示意图,在这里输入事件与叠加事件具有相同的路由 ID。需要注意,一个输入线事件与一个叠加线事件成首尾相连状态时(如下图中的事件a与A),会产生一个零长度事件。
点事件表与线事件表以求交方式叠加产生一个新的点事件表,而使用求并方式叠加产生一个新的线事件表。点线叠加与线点叠加的结果事件表类型相同。 下图为一个点事件表和一个线事件表叠加的示意图。采用求并方式叠加时,点事件处和点事件与线事件的相交处会产生零长度事件,比如图中的点事件2与线事件 a 叠加产生零长度事件 2a。
两个点事件表叠加的结果为一个点事件表。由于其分析的意义不大,因此在实际应用中较少用到。用户可根据实际研究的需要来使用,在此不做赘述。
- 参数:
inputEventsParameter
- 指定的输入事件参数设置。overlayEventParameter
- 指定的叠加事件参数设置。eventOverlayType
- 指定的事件叠加类型。outputDatasource
- 指定的用于存储结果事件表的数据源。如果设为 null,则将结果事件表输出到输入事件所在的数据源。outputDatasetName
- 指定的结果数据集的名称。resultEventsParameter
- 指定的叠加结果事件参数设置。tolerance
- 指定的叠加容限。单位与结果事件表的刻度值单位相同。isKeepField
- 指定是否保留属性字段。如果为 true 则会将输入事件表和叠加事件表中除系统字段外的属性字段写入结果事件表,名称以“_in”结尾的字段表示来自输入事件表,以“_over”结尾的字段表示来自叠加事件表;指定为 false 则不写入。isKeepZeroLengthEvents
- 指定是否保留零长度线事件。如果为 true,则叠加产生的零长度事件会写入结果事件表中,false 则不会写入。listeners
- 用于接收进度条事件的监听器。- 返回:
- 叠加结果数据集;叠加失败则返回 null。
- 示范代码:
- 以下代码示范了如何进行事件表的叠加。
使用本示例代码,请确保在您的项目中存在一个名为“mapControl”的地图控件,并声明一个名为“m_workspace”的工作空间(
Workspace
)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。private void EventTableOverlayExample() { // 获取进行叠加的两个事件表,这里获取一个点事件表和一个线事件表 Datasource datasource = m_workspace.getDatasources().get( "LinearReferencing"); DatasetVector eventTablePoint = (DatasetVector) datasource.getDatasets() .get("PointEventTab"); DatasetVector eventTableLine = (DatasetVector) datasource.getDatasets() .get("LineEventTab"); // 构造一个 RouteEventsParameter 对象并设置输入事件参数 RouteEventsParameter inputEventParameter = new RouteEventsParameter(); inputEventParameter.setEventDataset(eventTablePoint); inputEventParameter.setRouteIDField("ROUTEID"); inputEventParameter.setMeasureField("MEASURE"); // 构造一个 RouteEventsParameter 对象并设置叠加事件参数 RouteEventsParameter overlayEventParameter = new RouteEventsParameter(); overlayEventParameter.setEventDataset(eventTableLine); overlayEventParameter.setRouteIDField("ROUTEID"); overlayEventParameter.setMeasureStartField("STARTMEASURE"); overlayEventParameter.setMeasureEndField("ENDMEASURE"); // 构造一个 RouteEventsParameter 对象并设置结果事件参数 RouteEventsParameter resultEventParameter = new RouteEventsParameter(); resultEventParameter.setRouteIDField("ROUTEID"); resultEventParameter.setMeasureField("MEASURE"); resultEventParameter.setMeasureStartField("STARTMEASURE"); resultEventParameter.setMeasureEndField("ENDMEASURE"); // 调用 OverlayRouteEvents 方法实现事件表的叠加,叠加类型设置为”求交“ DatasetVector resultOverlayEventTable = LinearReferencing .overlayRouteEvents(inputEventParameter, overlayEventParameter, EventOverlayType.EVENT_INTERSECT, datasource, "EventOverlayResult", resultEventParameter, 0.0, true, false); if (resultOverlayEventTable != null) { JOptionPane.showMessageDialog(null, "事件表叠加成功!"); } }
-
rebuildSpatialData
@Deprecated public static boolean rebuildSpatialData(DatasetVector eventTable)
已过时。 此方法已废弃,请使用支持进度监听的新方法LinearReferencing.rebuildSpatialData(DatasetVector, SteppedListener...)
替换。当已存在动态分段关系的事件表被修改后,重新生成对应的空间数据。该方法适用于下面的情形:
事件表 E 已经根据路由数据集 R 生成了对应的空间数据 D,此时三者建立了动态分段关系。当事件表 E 的记录发生变化,如增加、删除、修改记录等(注意不包括对字段的增删改),应用该方法可以根据修改后的事件表 E 生成新的空间数据 D,并自动覆盖原来的空间数据,从而不需要先删除动态分段关系再删除空间数据 D,然后再生成同名的空间数据 D。当上一次生成的空间数据正在使用不允许删除时,使用此方法更新动态分段的结果非常有用。
注意,使用该方法的前提是指定的事件表存在动态分段关系。生成空间数据使用的参数与该事件表上一次生成空间数据时相同,生成的结果将直接覆盖事件表上一次生成的空间数据。
- 参数:
eventTable
- 指定的要重新生成空间数据的事件表。- 返回:
- 一个布尔值,代表是否生成成功。如果成功,返回 true,否则返回 false。
-
rebuildSpatialData
public static boolean rebuildSpatialData(DatasetVector eventTable, SteppedListener... listeners)
当已存在动态分段关系的事件表被修改后,重新生成对应的空间数据。该方法适用于下面的情形:
事件表 E 已经根据路由数据集 R 生成了对应的空间数据 D,此时三者建立了动态分段关系。当事件表 E 的记录发生变化,如增加、删除、修改记录等(注意不包括对字段的增删改),应用该方法可以根据修改后的事件表 E 生成新的空间数据 D,并自动覆盖原来的空间数据,从而不需要先删除动态分段关系再删除空间数据 D,然后再生成同名的空间数据 D。当上一次生成的空间数据正在使用不允许删除时,使用此方法更新动态分段的结果非常有用。
注意,使用该方法的前提是指定的事件表存在动态分段关系。生成空间数据使用的参数与该事件表上一次生成空间数据时相同,生成的结果将直接覆盖事件表上一次生成的空间数据。
- 参数:
eventTable
- 指定的要重新生成空间数据的事件表。listeners
- 用于接收进度条事件的监听器。- 返回:
- 一个布尔值,代表是否生成成功。如果成功,返回 true,否则返回 false。
-
createMarkPoints
@Deprecated public static DatasetVector createMarkPoints(CreateMarkPointsParameter parameter)
已过时。 此方法已废弃,请使用支持进度监听的新方法LinearReferencing.createMarkPoints(CreateMarkPointsParameter, SteppedListener...)
替换。创建路由数据中刻度值点。- 参数:
parameter
- 创建刻度值点参数类。- 返回:
- 刻度值点数据集。
-
createMarkPoints
public static DatasetVector createMarkPoints(CreateMarkPointsParameter parameter, SteppedListener... listeners)
创建路由数据中刻度值点。- 参数:
parameter
- 创建刻度值点参数类。listeners
- 用于接收进度条事件的监听器。- 返回:
- 刻度值点数据集。
-
addSteppedListener
public static void addSteppedListener(SteppedListener l)
添加一个进度条事件(SteppedEvent
)的监听器。- 参数:
l
- 一个用于接收进度条事件的监听器。
-
removeSteppedListener
public static void removeSteppedListener(SteppedListener l)
移除一个进度条事件(SteppedEvent
)的监听器。- 参数:
l
- 一个用于接收进度条事件的监听器。
-
-
Copyright © 2021–2024 SuperMap. All rights reserved.