ProConcepts Linear Referencing - Esri/arcgis-pro-sdk GitHub Wiki

The Linear Referencing API concepts will cover the capabilities of the Pro SDK for linear referencing and dynamic segmentation.

Language:      C#
Subject:       Geodatabase
Contributor:   ArcGIS Pro SDK Team <[email protected]>
Organization:  Esri, http://www.esri.com
Date:          10/06/2024
ArcGIS Pro:    3.4
Visual Studio: 2022

In this topic

Introduction

Many organizations gather data about linear features like highways, city streets, railroads, rivers, and water and sewer networks. This data is described using x and ycoordinates in a two-dimensional coordinate system. This system is suitable for keeping track of features with fixed characteristics. However, a one-dimensional linear referencing system is used to dynamically represent these linear features' characteristics.

The linear referencing system stores data using a relative position along a measured linear feature, and the feature's location is determined using a linear system of measured value instead of x and y coordinates. For example, the road construction starts at Mile 15 instead of 30o40'25'' N, 96o22'32'' W .

The ArcGIS.Core.Data.LinearReferencing namespace provides functionality for working with linear referencing datasets, such as accessing routes, measures, and events, building dynamic segmentation, and locating features along routes.

Routes

Routes are the linear features in an M-enabled polyline feature class with a unique route identifier field and measure value. This measure value defines discrete locations along the linear feature.

The RouteInfo class represents information about a route feature class, such as RouteIDFieldName (a unique route identifier) and the underlying route feature class that can be accessed from RouteInfo.GetRouteFeatureClass() as:

using (FeatureClass routesFeatureClass = geodatabase.OpenDataset<FeatureClass>("Roads"))
{
    RouteInfo routeInfo = new RouteInfo(routesFeatureClass, "RID");
}

A route feature class can be created using the DDL operation, as shown below.

public void CreateRouteFeatureClass(SchemaBuilder schemaBuilder)
{
    FieldDescription routeIdDescription = FieldDescription.CreateIntegerField("RouteID");
    FieldDescription routeNameDescription = FieldDescription.CreateStringField("RouteName", 100);
    ShapeDescription shapeDescription = new ShapeDescription(
                     GeometryType.Polyline, SpatialReferences.WGS84) { HasM = true, HasZ = false };

    FeatureClassDescription routeFeatureClassDescription = new FeatureClassDescription(
          "Routes", new List<FieldDescription>() { routeIdDescription, routeNameDescription }, shapeDescription);

    //Create an M-enabled poly-line feature class 
    schemaBuilder.Create(routeFeatureClassDescription);
    schemaBuilder.Build();
}

Measures

Measures are values stored along a linear feature representing a location relative to the beginning of the feature or some point along it. It can be any unit of measurement, such as miles, meters, feet, time, etc. Each route vertex stores measure value (X, Y, and M-value). The measure values (M-values) are independent of the coordinates of a route feature class and can arbitrarily increase, decrease, or remain constant along the linear feature.

Event features can be identified using measurements along the line (route) in the following diagram as -

  • point event at measure 12 along the line
  • point event at 4 units east of measure marker 10 along the line
  • line event starts at measurement 18 and ends at 26

The Geometry Engine interface performs various measure-related operations, such as check if M-values are numbers, get minimum and maximum M-values, set M-values at a distance, multiply M-values, etc.

Events

An event is a linear or point feature that occurs on or describes a route feature. Events are stored in a route event table, with each row representing an event and its location expressed as measurements along a route feature. For example, a highway event table might include speed limits, road quality/condition, construction zones, and accidents.

A point event represents a discrete location along a route, such as a highway mile marker or an accident location. Similarly, a line event describes a portion of a route, such as construction zones or reduced-speed areas.

The EventInfo class represents information about the event table. The PointEventInfo describes a measure, offset, and the unique route identifier fields. Similarly, the LineEventInfo holds information about the beginning and end of events in addition to the offset and unique route identifier fields.

using (Table eventsTable = geodatabase.OpenDataset<Table>("Accidents"))
{
    EventInfo eventInfo = new LineEventInfo(eventsTable, "RID", "fromMeasure", "toMeasure");
}

Dynamic Segmentation

Dynamic segmentation is the process of computing the shape (map location) of events stored in an event table along linear features.

Linear features such as highways, railroads, rivers, and pipelines typically have only one set of attributes, but dynamic segmentation provides an intuitive way to allow multiple attributes to be independently associated with any portion of an existing linear feature. These attributes can be displayed, queried, edited, and analyzed without affecting the underlying linear feature's geometry.

For example, users often have to document various characteristics of roads. Without using linear referencing, this could result in roads being divided into multiple small segments at each point where attribute values like number of lanes, road material, speed, and condition change. Dynamic segmentation enables these scenarios to be handled as linear referencing events along the roads, as illustrated in the figure below:

The result of the dynamic segmentation process is a dynamic feature class between routes and route events, known as the route event source.

Route Event Source

A route event source is a dynamic feature class that stores and manages information about events occurring along routes. Events are typically stored in an event table, which can be operated as a dynamic feature class by computing each row as an individual feature.

The RouteEventSource constructor takes RouteInfo, EventInfo, and RouteEventSourceOptions as parameters to create a dynamic feature class, i.e., RouteEventSource.

The RouteEventSourceOptions defines a configuration that creates a RouteEventSource. Advanced dynamic segmentation options such as event locating angles, point events as multipoint features, offset direction, and event locating errors are also available depending on whether you are visualizing point events or line events.

The PointEventRouteSourceOptions defines a configuration to create a RouteEventSource from point events. If an angle type is provided in the PointEventRouteSourceOptions constructor, the LOC_ANGLE column will be added in the RouteEventSource to display the angle of the route where the event is placed.

// Dynamic segmentation process calculates the normal (perpendicular) angle of the route where the event is placed
RouteEventSourceOptions pointEventSourceOptions = new PointEventSourceOptions(AngleType.Normal) 
{ 
    // Calculates the complement of normal angle 
    ComplementAngle = true,
    AddErrorField = true
};

If the AddErrorField property is true, the LOC_ERROR column will be added in the RouteEventSource to illustrate locating errors during a RouteEventSource creation. These errors can also be accessed from RouteEventSource.GetErrors().

Similarly, the LineEventRouteSourceOptions defines a configuration to create a RouteEventSource from line events.

When IsPositiveOffsetOnRight is set to true, a positive offset will be displayed to the right of the route. To use this property, you must specify the offset field name in the EventInfo object.

public void ViewRoadPavementConditions(Geodatabase geodatabase, string routeFeatureClassName = "Roads", 
               string eventTableName = "Pavements", string routeIdFieldName = "RID", 
               string fromMeasureFieldName = "fromMeasure", string toMeasureFieldName = "toMeasure")
{
    using (FeatureClass routesFeatureClass = geodatabase.OpenDataset<FeatureClass>(routeFeatureClassName))
    using (Table eventsTable = geodatabase.OpenDataset<Table>(eventTableName))
    {
        RouteInfo routeInfo = new RouteInfo(routesFeatureClass, routeIdFieldName);
        EventInfo eventInfo = new LineEventInfo(
                    eventsTable, routeIdFieldName, fromMeasureFieldName, toMeasureFieldName);
        RouteEventSourceOptions routeEventSourceOptions = 
                         new LineEventSourceOptions() { IsPositiveOffsetOnRight = true };

        using (RouteEventSource routeEventSource = 
                     new RouteEventSource(routeInfo, eventInfo, routeEventSourceOptions))
        using (RouteEventSourceDefinition routeEventSourceDefinition = routeEventSource.GetDefinition())
        {
            // Locating errors 
            IReadOnlyList<RouteEventSourceError> errors = routeEventSource.GetErrors();

            // Route event source fields 
            IReadOnlyList<Field> routeEventSourceFields = routeEventSourceDefinition.GetFields();
        }
    }
}

The RouteEventSourceDefinition represents the metadata of RouteEventSource which inherits from the FeatureClassDefinition.

To visualize a route event source in ArcGIS Pro, create a route event source layer (a temporary feature layer using routes and route events) using FeatureLayerCreationParams and add it to the map as illustrated below.

// Add route event source layer in the ArcGIS Pro
FeatureLayerCreationParams layerParams = new FeatureLayerCreationParams(routeEventSource)
{
    Name = "PavementConditions"
};

LayerFactory.Instance.CreateLayer<FeatureLayer>(layerParams, MapView.Active.Map);

The shapes of a RouteEventSource cannot be edited because the dynamic segmentation process dynamically generates them. Editing event attributes in the RouteEventSource will update the underlying event table.

Route event sources can be created between two different data store types. For example, routes from a file geodatabase and events from an enterprise geodatabase can be used to create a route event source using a dynamic segmentation process.

Locate Features Along Routes

Locate features along the routes allows us to determine the route and measure information at locations where input features (point, line, or polygon) intersect the routes. This functionality is useful for finding information such as passenger stops along bus routes, construction zones along highways, manholes along city streets, and so on.

The RouteInfo.LocateFeatures method computes the intersection of input features and routes and writes the route and measure information to a new event table described by the EventTableConfiguration. Feature selection can be used to decrease the number of input features.

The PointEventTableConfiguration describes the configuration for creating an event table to store point events, and the LineEventTableConfiguration defines the configuration for storing line events.

When locating point features along routes, each point feature's route and measure information is computed and written to a point event table.

Similarly, when locating line or polygon features along route, the feature's start and end measure information is calculated at the intersection of the line or polygon and route data and written to a line event table.

public void FindSlowTrafficZonesAlongRoads(Geodatabase geodatabase, string routeFeatureClassName = "Roads", 
                              string eventTableName = "TrafficTime", string routeIdFieldName = "RID", 
                              string fromMeasureFieldName = "fromMeasure", string toMeasureFieldName = "toMeasure")
{
    // Configure an event table
    EventTableConfiguration lineEventTableConfiguration = new LineEventTableConfiguration(
        eventTableName, routeIdFieldName, fromMeasureFieldName, toMeasureFieldName) 
        { 
            KeepAllFields = true, 
            MDirectionOffset = true 
        };

    using (FeatureClass routeFeatureClass = geodatabase.OpenDataset<FeatureClass>(routeFeatureClassName))
    using (FeatureClass slowZonesFeatureClass = geodatabase.OpenDataset<FeatureClass>("SlowZones"))
    {
        RouteInfo routeInfo = new RouteInfo(routeFeatureClass, routeIdFieldName);

        // Creates an event table with route and measure information in the geodatabase
        routeInfo.LocateFeatures(slowZonesFeatureClass, 0.5, lineEventTableConfiguration);        
    }
}

To successfully locate the features, they must be found within a specified tolerance of the routes. The search tolerance for points specifies a search radius; for lines, it specifies a cluster tolerance and does not apply to polygons.

⚠️ **GitHub.com Fallback** ⚠️