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
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 y
coordinates 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 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 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.
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 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.
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 ofRouteEventSource
which inherits from theFeatureClassDefinition
.
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 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.