根据点或线事件表生成空间数据。如果是线事件表,生成的是路由数据集。

命名空间:  SuperMap.Analyst.SpatialAnalyst
程序集:  SuperMap.Analyst.SpatialAnalyst (in SuperMap.Analyst.SpatialAnalyst)
版本: dll

语法

C#
public static DatasetVector GenerateSpatialData(
	GenerateSpatialDataParameter parameter
)

参数

parameter
Type: SuperMap.Analyst.SpatialAnalyst..::.GenerateSpatialDataParameter
指定的生成空间数据参数设置。

返回值

由事件表构建出来的空间数据。

备注

事件表用属性表的方式记录了点或者线事件发生所在的路由、刻度、事件的描述信息(如交通事故发生地的天气状况、驾驶者的酒精含量、当时的车速、路面宽度、铺设材料等)。如下图所示,生成空间数据就是根据路由数据集,将事件表中的事件定位到空间上,生成相应的点或者线数据,并建立和存储三者间的动态分段关系的过程。其中点事件对应生成点数据集,线事件表对应生成的线数据为路由数据集。动态分段关系隐含存储在数据集中,记录了路由数据集、事件表与生成的空间数据三者间的对应关系,是进行联动修改(即修改三者中的一个,其他两个根据规则自动进行修改)也就是动态分段的依据。

  • 生成的空间数据的类型
  • 通过该方法生成空间数据时,生成的结果是点数据还是线数据,由指定的参数决定。在生成空间数据参数设置(GenerateSpatialDataParameter)对象中,只要通过 MeasureField 属性指定了事件表中有效的刻度值字段,则生成的空间数据为点数据。因此,如果想要生成线数据,就需要指定有效的起始刻度字段和终至刻度字段,并且注意不能同时指定刻度值字段(MeasureField)。

  • 动态分段关系
  • 生成空间数据涉及三个角色:路由数据集、事件表和空间数据。生成空间数据时,系统会建立并存储三者的动态分段关系,即根据路由 ID、刻度值字段等信息建立起三者的对应关系。动态分段关系主要用于实现三个角色间的联动修改。

    如下图所示,在动态分段关系中,路由数据集与事件表为一对多的关系,路由数据集与空间数据为一对多的关系,事件表与空间数据为一对一的关系。也就是说,路由数据集可以被多个事件表共用从而生成多个空间数据,但一个事件表只能对应一个空间数据。

    SuperMap 提供了动态分段关系管理(DynamicSegmentManager)类,用于对动态分段关系进行检查和删除。

  • 路由、事件表和空间数据的联动
  • 生成空间数据之后,用于生成空间数据的路由数据集、事件表与生成的空间数据之间就建立了动态分段关系。有了该关系,在修改三者中的一个时,按照约定,其他两者会自动发生相应的变化,SuperMap 称之为联动修改,是动态分段功能的重要特征。

    目前,SuperMap 支持以下几种联动:

    1. 事件的描述信息发生变化。这种情况在事件表与空间数据之间发生联动。
    2. 修改事件的描述信息,是指修改除路由标识字段和刻度字段之外的一般属性字段,如公路限速信息可能由于天气、施工等原因会做临时性修改。如果修改事件表中的描述信息,从该事件表生成的空间数据的属性信息也会自动进行相应的修改。同样的,修改空间数据属性表中的一般属性字段时,其对应的事件表也会动态改变。

    3. 事件发生的路由位置发生变化。这种情况在事件表与空间数据之间发生动态变化。

      修改事件发生的位置,是指修改事件表或空间数据中的刻度值字段。如果修改事件表中某条记录(事件)的刻度值,那么对应的空间数据中该事件对应的点或者线对象的几何信息和属性表中对应记录的刻度字段也会做相应修改;如果修改生成的空间数据的属性表中的刻度字段的值,对应的对象的几何信息也会修改,事件表中的相关联的事件的刻度字段的值也会动态发生同等变化。如果是线事件,可以修改起始刻度或者终止刻度,事件的长度和位置可能发生变化。如下图所示,是生成空间数据之后,将对应事件表中第一条事件的起始刻度和终止刻度由(20.78,79.37)修改为(150.00,180.00)前后,对应空间数据中对应该事件的线的变化,可以看出,当事件的刻度值发生变化后,对应的空间数据也自动进行对应的修改。

    4. 需要注意:如果修改后线事件的起始或终止 M 值超出了它所对应的路由的 M 值范围,则修改无效,对应的空间数据也不会发生变化。例如,修改事件表中某线事件的起始刻度和终止刻度为 18、60,而对应路由的 M 值范围为 3 到 20,则该条记录以及空间数据的几何信息都不会改变。

    5. 事件发生的路由改变。这种情况下,空间数据会根据路由数据集的修改发生变化,而修改空间数据时,对应的路由数据不会发生变化;事件表与空间数据之间会发生联动修改。

      这种情况适用于由于数据错误或者变更导致事件所发生的路由需要修改的情形,具体分为以下三种情形:

      • 如果修改的是路由对象的空间几何信息,对应的空间数据中相关对象的几何信息也会自动修改。如果发生事件的路由的位置和刻度值发生变化,如管道维修后走向发生了变化,它的形状和刻度值可能都需要修改。这时就需要对路由对象本身的空间几何信息进行修改,如旋转、移动,修改刻度值等。修改后,对应的空间数据中相关对象的几何信息会作相应的变化,即对应的事件和空间数据将重新定位。
      • 如果修改的是事件表的中某记录的路由 ID,则空间数据中与之关联的对象的几何信息和属性表中的路由ID字段也会随之动态改变。如下图中的事件表及其对应的空间数据,将事件表中第一条记录的路由 ID 由1改为2之后,该记录对应的空间数据也发生了变化,被定位到了 ID 为2的路由上面,正如下图(下)所展示的一样。
      • 如果修改的是生成的空间数据的路由 ID,则事件表中对应记录的路由 ID 值也会改变,同时,空间数据的几何信息也会根据修改后对应的路由而进行修改。

    6. 注意:如果修改路由数据集属性表中路由ID字段的值,该属性表可以修改成功,但对应的事件表和空间数据不会发生变化。

    目前,不支持修改事件表表结构和增删表记录的联动,但提供 RebuildSpatialData 方法,用于对事件表的记录进行增删改等修改后,重新生成对应的空间数据。

  • 注意:
    1. 用于生成空间数据的事件表中必须包含路由标识字段和刻度字段(点事件包含刻度字段,线事件包含起始刻度字段和终止刻度字段)。路由标识字段的值用于将事件对应的点或线定位到正确的路由上,刻度字段的值使事件对应的点或线最终正确定位。事件表中的路由标识字段、刻度字段及其他描述事件的属性,都会写入生成的空间数据的属性表中。
    2. 通过该方法生成空间数据时,系统会在结果数据集中添加一个名为“Event_SMID”的字段,用于存储事件表中对应事件的 SMID。特别需要注意的是,不能修改该字段,否则可能导致联动的结果错误。
    3. 由于事件表与空间数据为一对一关系,如果某事件表已经具有了一个动态分段关系,则不能再次用于生成空间数据,除非将其关系删除。因此,在调用 GenerateSpatialData 方法生成空间数据前,应先使用 DynamicSegmentManager 类的 GetDynamicSegmentInfos 方法检查事件表是否存在动态分段关系,如果存在则调用 RemoveDynamicSegmentInfos 方法删除关系。但请注意,可以使用 RebuildSpatialData 方法重新生成同名的空间数据,此时不必删除动态分段关系。
    4. 校准、事件表融合、线参考点刻度生成路由时,如果使用的数据集包含动态分段关系,则可能引起不必要的联动修改,导致之后的分析出现错误的结果。因此建议不要直接使用包含动态分段关系的数据集,可以拷贝该数据集,或先删除该数据集的动态分段关系(需谨慎执行此步骤,因为一旦删除动态分段关系,该关系的三个角色间将不存在关联,不能再进行联动修改)。
    5. 建立了动态分段关系后,如果直接删除一个存在动态分段关系的数据集(路由数据集、事件表或空间数据),会抛出异常,必须先将其动态分段关系删除,才能将该数据集删除。因此,建议在使用动态分段功能时,凡是进行删除数据集的操作,都先检查并删除或直接删除其动态分段关系。

有关生成空间数据、动态分段关系和联动修改的内容,请阅读动态分段技术文档的 10 生成空间数据一章。

示例

示例一:以下代码示范了如何根据线事件表和路由数据集生成对应的线空间数据。

使用本示例代码,请确保在您的项目中存在一个名为 mapControl 的地图控件(MapControl),并声明一个名为 m_workspace 的工作空间(Workspace)变量,打开位于安装目录\SampleData\LinearReferencing 目录下的工作空间 LinearReferencing.smwu,并将地图控件与工作空间关联。

CopyC#
private void GenerateSpatialDataExample()
{
    //获取用于生成空间数据的路由数据集
    Datasource datasource = m_workspace.Datasources["LinearReferencing"];
    DatasetVector referenceLineM = datasource.Datasets["Roads_M"] as DatasetVector;

    //获取用于生成空间数据的事件表数据集
    //避免破坏原始数据,所以复制一份数据,用于生成空间数据
    if (datasource.Datasets.Contains("LineEventTab_1"))
    {
        datasource.Datasets.Delete("LineEventTab_1");
    }
    DatasetVector eventTable = datasource.CopyDataset(datasource.Datasets["LineEventTab"], "LineEventTab_1", EncodeType.None) as DatasetVector;

    //构造一个 GenerateSpatialDataParameter 对象并设置相关参数
    GenerateSpatialDataParameter parameter = new GenerateSpatialDataParameter();
    parameter.EventTable = eventTable;
    parameter.EventRouteIDField = "ROUTEID";
    parameter.ReferenceLineM = referenceLineM;
    parameter.RouteIDField = "ROUTEID";
    parameter.MeasureStartField = "STARTMEASURE";
    parameter.MeasureEndField = "ENDMEASURE";
    parameter.ErrorInfoField = "ERROR";
    parameter.OutputDatasetName = "LineSpatialData";

    if (datasource.Datasets.Contains("LineSpatialData"))
    {
        //判断该数据集是否存在动态分段关系,如存在则删除关系
    DatasetVector dynamicDataset = datasource.Datasets["LineSpatialData"] as DatasetVector;
    DynamicSegmentInfo[] infos = DynamicSegmentManager.GetDynamicSegmentInfos(dynamicDataset);
    if (infos.Length != 0)
    {
        DynamicSegmentManager.RemoveDynamicSegmentInfos(dynamicDataset);
    }
        datasource.Datasets.Delete("LineSpatialData");
    }

    //调用 GenerateSpatialData 方法来生成空间数据
    DatasetVector resultSpatialDataset = LinearReferencing.GenerateSpatialData(parameter);

    if (resultSpatialDataset != null)
    {
        MessageBox.Show("生成空间数据成功!");
    }

    //将路由和生成的空间数据加载到地图上
    mapControl.Map.Layers.Add(referenceLineM, false);
    mapControl.Map.Layers.Add(resultSpatialDataset, true);
    mapControl.Map.Refresh();
}

示例二:以下代码示范了在生成空间数据之后,如何进行事件表与空间数据的联动修改。

使用本示例代码,需要确保先使用示例一生成了空间数据(由事件表"LineEventTab_1"和路由数据集(Roads_M)生成空间数据(LineSpatialData)),并且相关数据集没有被删除,其所在数据源没有被关闭。

本示例中,通过修改事件表“LineEventTab_1”中的路况字段(BLOCK)的部分值,修改后,可观察对应的空间数据“LineSpatialData”是否联动修改。

CopyC#
private void ModifyEventTableExample()
{
    //获取要修改的事件表,这里获取线事件表"LineEventTab_1"
    Datasource datasource = m_workspace.Datasources["LinearReferencing"];
    DatasetVector eventTable = datasource.Datasets["LineEventTab_1"] as DatasetVector;
    //获取该事件表的记录集
    Recordset recordset = eventTable.Query("BLOCK='M'", CursorType.Dynamic);

    //将事件表中路况为“拥堵”的事件修改为“缓行”。字段值 M 表示拥堵,N 表示缓行。
    recordset.MoveFirst();
    for (Int32 i = 0; i < recordset.RecordCount; i++)
    {
        recordset.Edit();
        recordset.SetFieldValue("BLOCK", "N");
        recordset.Update();
        recordset.MoveNext();
    }
    recordset.Close();
    recordset.Dispose();

    //加载线事件表对应的空间数据和路由到地图上
    mapControl.Map.Layers.Clear();
    DatasetVector spatialData = datasource.Datasets["LineSpatialData"] as DatasetVector;
    DatasetVector referenceLineM = datasource.Datasets["Roads_M"] as DatasetVector;
    mapControl.Map.Layers.Add(spatialData, false);
    mapControl.Map.Layers.Add(referenceLineM, false);
    mapControl.Map.Refresh();
}

请参见