Location


Supported with:
  • Engine
  • ArcView
  • ArcEditor
  • ArcInfo
  • Server
Library dependencies: System, SystemUI, Geometry, Display, Server, Output, Geodatabase, GISClient, DataSourcesFile, DataSourcesGDB, DataSourcesOleDB, DataSourcesRaster, DataSourcesNetCDF, GeoDatabaseDistributed, GeoDatabaseExtensions, Carto, NetworkAnalysis

Additional library information: Contents, Object Model Diagram

The Location library contains objects that support geocoding and linear referencing.

See the following sections for more information about this namespace:

Geocoding objects

Geocoding objects provide a framework to create and manage address locators. Locator objects create geometry for nonspatial descriptions of locations. An AddressLocator creates geometries for text representing addresses. AddressLocators can be stored on disk, in a file, or in a personal or ArcSDE geodatabase. AddressLocators can also be used to create GeocodeServer objects that are served using ArcGIS Server. Geocoding objects also provide an extensible framework for creating new types of custom locators.

Locator workspaces

A locator workspace contains locators and templates to create new locators or locator styles. The LocatorWorkspace abstract class allows you to create, store, and retrieve its locators and locator styles. The following are the main types of workspaces for locators— each type corresponds to the storage mechanism used for its locators:
  • DatabaseLocatorWorkspace contains locators stored in a file, personal, or ArcSDE geodatabase.
  • LocalLocatorWorkspace contains locators stored in a single folder on disk. The default LocalLocatorWorkspace stores the system locator styles.
  • AGSLocatorWorkspace contains locators that are served as GeocodeServers by an ArcGIS Server.

LocatorManager

LocatorManager is an object that retrieves LocatorWorkspace objects from the file system, geodatabase, or an ArcGIS Server. See the following illustration:

ILocatorWorkspace

Use ILocatorWorkspace to manage the locators and locator styles in a locator workspace. You can use this interface to retrieve Locator and LocatorStyle objects from the locator workspace, as well as create, modify, and delete locators contained in the workspace.
Use the GetLocator and GetLocatorStyle methods to retrieve locators and locator styles, respectively, by name from a LocatorWorkspace. The GetLocators and GetLocatorNames methods return enumerations of Locator and LocatorName objects, respectively, from the LocatorWorkspace, while the AddLocator method adds a new locator to the workspace.
Use RebuildLocator in ILocatorWorkspace2 to rebuild an address locator, particularly if the reference data was modified. See the following illustration:
When using the methods on ILocatorWorkspace to refer to locators in an ArcSDE database and styles by name, specify a user name as part of the Locator or LocatorStyle name. The names of ArcSDE locators and locator styles stored in a DatabaseLocatorWorkspace are prefixed with the ArcSDE user's name.
Some of the methods on ILocatorWorkspace require you to pass a locator category as a parameter. AddressLocators and AddressLocatorStyles used with ArcGIS have a category of Address.

Address locator reference data

Reference data objects are used to specify and manage the reference data used by ESRIFDOAddressLocators. See the following illustration:
Each ESRIFDOAddressLocator has a ReferenceDataTableEnumerator, which is an enumeration of ReferenceDataTable objects used by the locator.
Use the Tables property on IReferenceDataTables on the locator or locator style to get the ReferenceDataTableEnumerator.
Use ReferenceDataTable objects to specify the FDO data sources that an ESRIFDOAddressLocator uses. The Name property on IReferenceDataTable returns a reference to a TableName object that represents the FDO data source used as reference data by the locator.
Each ReferenceDataTable has an enumeration of ReferenceDataIndex objects, which specify the geocoding indexes that an ESRIFDOAddressLocator uses to find potential candidates for addresses. ReferenceDataTable objects also have enumerations of ReferenceDataField objects, which are used to specify fields in the FDO data source that contain address information.

Address locators

Locator is an abstract class that creates geometry for nonspatial descriptions of locations. All types of locators, including address locators and route locators, are subclasses of the Locator abstract class. See the following illustration:
AddressLocator objects create geometry for text descriptions of addresses (geocoding). Address locators find candidates for addresses, geocoding tables of addresses, and single addresses.

IAddressGeocoding

The IAddressGeocoding interface is the primary interface used to geocode addresses.
Use the MatchAddress method to geocode a single address. The address parameter is a PropertySet containing properties that represent the input address components used by the locator. See the following illustration:
Use the AddressFields property on the IAddressInputs interface to determine the input address components used by the locator.
The MatchFields property returns a fields collection where the field object names correspond to the names of the properties in the PropertySet returned by the MatchAddress method.
IBatchGeocoding provides access to additional geocoding functionality. IBatchGeocoding can be used to match a recordSet or and rematch a geocoded feature class with modified locator properties if you are not satisfied with the results after geocoding a table of addresses.

IReverseGeocoding and IReverseGeocodingProperties

IReverseGeocoding and IReverseGeocodingProperties provide access to members to find the address closest to a point. Use the SearchDistance property to define the maximum search tolerance in units specified by SearchDistanceUnits to use when searching for an address represented by a point. See the following illustration:
ReverseGeocode returns a PropertySet representing the address closest to the point passed as the location parameter. Project the point object passed to the location parameter into the spatial reference used by the locator before it is passed to ReverseGeocode.
Use the bReturnIntersection parameter to indicate if the ReverseGeocode method should return an intersection address. The names of the properties in the PropertySet correspond to the names of the field objects in the fields collection returned by AddressFields on IAddressInputs on the locator.
The following code example shows how to use IReverseGeocoding and IReverseGeocodingProperties to find the address closest to a point:

Geocode servers

GeocodeServer is a ServerObject served by ArcGIS Server that can be used to geocode addresses. Internally, a GeocodeServer uses an address locator to do geocoding and exposes the high-level functionality of the address locator using the IGeocodeServer interface. Generally, GeocodeServer objects will be used by ArcGIS Server developers to create server applications that include geocoding functionality.
ArcGIS Engine developers can use GeocodeServer objects to include geocoding functionality in custom applications using only the high-level geocoding functionality exposed by a GeocodeServer. See the following illustration:
The following code example shows how to use a GeocodeServer to geocode a single address:

Linear referencing

Linear referencing objects provide a framework for the creation, management, and display of linearly referenced data. These objects allow you to find and identify route locations and dynamically segment route events to display on a map. Additional objects are provided for route and event geoprocessing and for the enhanced cartographic display of routes and events.

Dynamic segmentation

The following illustration shows dynamic segmentation objects:
 

Dynamic segmentation concepts

Dynamic segmentation computes the shape of route locations along calibrated linear features at runtime based on event tables for which distance measures are available.
  • A calibrated linear feature or route is a polyline feature that has m- (measure) values and an identifier.
  • Route locations can be organized into tables based on a common theme (event tables)—for example, five event tables containing information on speed limits, year of resurfacing, present condition, signs, and accidents can reference a route feature class representing highways.
  • An event table is any table that contains a route identifier field and at least one measure field. Tables containing point route locations have one measure field, while tables containing line route locations have two. The route identifier field matches the route identifier in the route feature class (does not have to have the same name).

    See the following illustration:

  • A route event source serves an event table as a dynamic feature clas. Every row in the table is served as a feature whose shape is calculated on-the-fly everytime it is requested (dynamic segmentation).
  • In a route event source, there is one feature for every row in the original event table. However, sometimes the features have empty shapes (for some reason, the event could not be located). Other times, an event can only be partially located (occurs for line events only); there are sample error codes.

    See the following illustration:

Locator

Locator is an abstract class that specifies the interfaces common to all types of locator objects. Types of locators include addresses, x,y coordinates, routes, and place names. Locators combine reference data and a location method. See the following illustration:

ILocator

The ILocator interface provides access to the properties of a locator. See the following illustration:

ILocatorFullName

The ILocatorFullName interface provides access to the name property of a locator so it can be persisted. See the following illustration:

RouteLocator

RouteLocator is an abstract class. A RouteLocator transforms a route location into a shape that can be displayed on a map. Route locations describe a precise location along a route or a portion of a route between a from- and to- measure. See the following illustration:

IRouteLocator2

The IRouteLocator2 interface inherits from IRouteLocator and is useful for retrieving the properties of a RouteLocator object and for determining the shape of route locations and events. See the following illustration:
Furthermore, the identify method is used to identify route locations using an envelope. To create this envelope use the envelope of the map document's current location expanded by the search tolerance. See the following code example:
[Java]
try{
    //Get a MapBean.
    MapBean mapBean = null;
    IEnvelope pEnvelope = mapBean.getExtent();
    //Get search tolerance, typically from ISelectionEnvironment.
    double searchTolerance = 0.1;
    pEnvelope.expand(searchTolerance, searchTolerance, false);
}

catch (Exception e){
    e.printStackTrace();
}
For route locators, RouteFeatureClass can be a coverage route system, a PolyLineM shapefile, or a PolyLine feature class (with m-values) in a personal, file, or ArcSDE geodatabase—routes are stored in a feature class where IGeometryDef.GetGeometryType = esriGeometryPolyLine and IGeometryDef.isHasM = true. See the following illustration:
 

RouteMeasureLocator

A RouteMeasureLocator is one type of RouteLocator. It determines the shape of a route location by matching the route location's m-values to those stored in a route feature. A RouteMeasureLocator is created via its name object counterpart, RouteMeasureLocatorName. See the following illustration:
 

IRouteLocatorName

IRouteLocatorName retrieves the properties of a RouteLocator object. See the following illustration:
  • LocatorName is an abstract class that can be used to refer to a Locator object.
  • RouteLocatorName is an abstract class that can be used to refer to a RouteLocator object.

RouteMeasureLocatorName

RouteMeasureLocatorName is a class that can be used to refer to a RouteMeasureLocator object. It is a specific implementation of LocatorName and RouteLocatorName. All route locator name classes implement the IRouteLocatorName interface. This interface is used for setting and retrieving the properties of a RouteLocatorName object. See the following:
  • RouteFeatureClassName is a polyline feature class with m-values.
  • RouteIDFieldName is any numeric or text field containing route identifiers. This field relates to a similar field in an event table.
  • RouteMeasureUnits are the units of the m-values stored in the routes. The default is esriUnknownUnits.
  • RouteWhereClause is a string that limits the number of routes on which route locations can be found.
The following code example shows how to create a RouteMeasureLocator via a RouteMeasureLocatorName:
[Java]
try{
    //Get A PolyLineM feature class. 
    IFeatureClass pRouteFC = null;

    IDataset pDS = new IDatasetProxy(pRouteFC);
    IRouteLocatorName pRtLocatorName = new RouteMeasureLocatorName();
    pRtLocatorName.setRouteFeatureClassNameByRef(pDS.getFullName());
    pRtLocatorName.setRouteIDFieldName("");
    pRtLocatorName.setRouteMeasureUnit(com.esri.arcgis.system.esriUnits.esriMeters);
    IName pName = new INameProxy(pRtLocatorName);
    pName.open();
}

catch (IOException ex){
    ex.printStackTrace();
}

RouteMeasureLocation

A RouteMeasureLocation describes a portion of a route or a single position along a route. See the following illustration:

IRouteLocation

The IRouteLocation interface defines the properties of a route location—for example, route locations occur along a single route; therefore, set that value here. Additionally, identify the units in which the route location was collected and specify whether you want the route location's shape offset from its route when it is located. See the following illustration:
Offsets are in the spatial reference units of the route feature class (not necessarily the same units as the route feature class' measures). Therefore, an offset on route data stored in geographic units can produce inconsistent results. Offsets are used for rendering purposes only.
Setting the IRouteLocation.MeasureUnit property (get/set) enables you to do on-the-fly measure conversion. This property corresponds to IRouteLocator.RouteMeasureUnit. For example, you may know the position of a route location in miles, but your route feature class has its measures stored in meters. By setting these values accordingly, you can achieve measure conversion.
RouteMeasureLineLocation is a class that describes portions of a route using from and to measure locations.

IRouteMeasureLineLocation

The IRouteMeasureLineLocation interface is where you set the route location's from- and to-measure values—for example, if you want to find a location from 2,500 meters to 3,500 meters along route 10. See the following illustration:
See the following code example if you want this location to be offset 25 meters from the route:
[Java]
try{
    IRouteLocation pRouteLoc = new RouteMeasureLineLocation();
    pRouteLoc.setMeasureUnit(com.esri.arcgis.system.esriUnits.esriMeters);
    pRouteLoc.setRouteID(10);
    pRouteLoc.setLateralOffset(25);
    IRouteMeasureLineLocation pRMLineLoc = new IRouteMeasureLineLocationProxy
        (pRouteLoc);
    pRMLineLoc.setFromMeasure(2500);
    pRMLineLoc.setToMeasure(3500);
}

catch (IOException ex){
    ex.printStackTrace();
}

IRouteMeasurePointLocation

A RouteMeasurePointLocation is a class that uses a single m-value to describe a single position along a route. Use IRouteMeasurePointLocation to set the route location's m-value. See the following illustration:
See the following code example if you want to find a location 565.5 meters along route 10:
[Java]
try{
    IRouteLocation pRouteLocation = new RouteMeasurePointLocation();
    pRouteLocation.setMeasureUnit(com.esri.arcgis.system.esriUnits.esriMeters);
    pRouteLocation.setRouteID(10);
    pRouteLocation.setLateralOffset(0);
    IRouteMeasurePointLocation pRMPointLoc = new IRouteMeasurePointLocationProxy
        (pRouteLocation);
    pRMPointLoc.setMeasure(565.5);
}

catch (IOException ex){
    ex.printStackTrace();
}
Once you have created a route location, determine its geometry by calling the IRouteLocator.Locate method (refer to the previous code examples to see how the RouteLocator object was created).
[Java]
try{
    IGeometry[] pGeom = null;
    IRouteLocator pRtLocator = null;
    IRouteLocation pRMPointLoc = null;
    int locError[] = null;

    pRtLocator.locate(pRMPointLoc, pGeom, locError);
    //LocError is an element array with
    //com.esri.arcgis.geodatabase.esriLocatingError constant.
}

catch (IOException ex){
    ex.printStackTrace();
}

RouteEventProperties

An event table stores route locations and associated attributes; therefore, an event is a row from an event table. For example, an event can be a speed limit of 110 km/h on route 50 from km 92 to 138. In this case, the route location information of route 50 between km 92 and 138 is used to reference an attribute to a particular portion of a route in a route feature class.
Create RouteEventProperties to identify certain characteristics of the table so it can be recognized as an event table. RouteEventProperties are helper objects for a RouteEventSource. See the following illustration:

IRouteEventProperties2

The IRouteEventProperties2 interface inherits from IRouteEventProperties and establishes the route key field, the measure units the events were collected in, and (optionally) the lateral offset field.
The AddErrorField method indicates whether you want an additional field added to your RouteEventSource for storing event-locating errors. See the following illustration:
The route key (EventRouteIDFieldName) defined on this interface is related to the RouteIDFieldName property on IRouteLocator and IRouteLocatorName (how events are located along the event respective routes).
The EventRouteIDFieldName does not have to have the same name as the RouteIDFieldName, but it must store similar data.

IRouteMeasureLineProperties

RouteMeasureLineProperties is a class used to specify the characteristics of a line event table. Use IRouteMeasureLineProperties to identify the line event table's from- and to-measure fields. Each line event's measure reflect the distance from the lowest measure along its route. See the following illustration:
 
See the following code example to set up line event properties where your table has an offset field:
[Java]
try{
    IRouteMeasureLineProperties pRMLP = new RouteMeasureLineProperties();
    IRouteEventProperties2 pRtProp = new IRouteEventProperties2Proxy(pRMLP);
    pRtProp.setAddErrorField(true);
    pRtProp.setErrorFieldName("LOC_ERROR");

    pRtProp.setEventMeasureUnit(com.esri.arcgis.system.esriUnits.esriMeters);
    pRtProp.setEventRouteIDFieldName("rKey");
    pRtProp.setLateralOffsetFieldName("Offset");

    IRouteMeasureLineProperties pRMLineProp = new IRouteMeasureLinePropertiesProxy
        (pRtProp);
    pRMLineProp.setFromMeasureFieldName("fmp");
    pRMLineProp.setToMeasureFieldName("tmp");

}

catch (IOException ex){
    ex.printStackTrace();
}

IRouteMeasurePointProperties2

The RouteMeasurePointProperties class specifies the characteristics of a point event table. IRouteMeasurePointProperties2 inherits from IRouteMeasurePointProperties and is where you identify the point event table's measure field. Each point event's measure reflects the distance from the lowest measure along its route. See the following illustration:
The AddAngleField method indicates whether you want a field added to your RouteEventSource to store the angle of the route where the point event is placed—useful for rotating marker symbols, and so on. The normal (perpendicular) or tangent angle can be calculated.
By default, when a point event is located along a route, a point feature is created. However, in some applications route measures are not unique. The AsPointFeature method provides the ability to create multipoint features.
See the following code example to set up point event properties on a table:
[Java]
try{
    IRouteMeasurePointProperties pRtProp1 = new RouteMeasurePointProperties();
    IRouteEventProperties2 pRtProp = new IRouteEventProperties2Proxy(pRtProp1);
    pRtProp.setAddErrorField(true);
    pRtProp.setErrorFieldName("LOC_ERROR");
    pRtProp.setEventMeasureUnit(com.esri.arcgis.system.esriUnits.esriMeters);
    pRtProp.setEventRouteIDFieldName("rKey");
    IRouteMeasurePointProperties2 pRMPointProp = new
        IRouteMeasurePointProperties2Proxy(pRtProp);
    pRMPointProp.setMeasureFieldName("mile");
    pRMPointProp.setAddAngleField(true);
    pRMPointProp.setAngleFieldName("LOC_ANGLE");
}

catch (IOException ex){
    ex.printStackTrace();
}

RouteEventSource

A RouteEventSource serves an event table as a dynamic feature class. Every row in the table is served as a feature whose shape is calculated on-the-fly each time it is requested (dynamic segmentation). See the following illustration: 

IRouteEventSource

To serve an event table as a feature class, a RouteEventSource needs to know the event table, RouteEventProperties, RouteLocator, and so on. IRouteEventSource retrieves this information. See the following illustration:
 

RouteEventSourceName

Similar to the locator objects previously discussed, a RouteEventSource is created via its name object counterpart, RouteEventSourceName. A RouteEventSourceName specifies a RouteEventSource object and can be used to instantiate it. See the following illustration:
 

IRouteEventSourceName

IRouteEventSourceName sets the event table, RouteEventProperties, and RouteLocator. See the following illustration:
The following code example shows how to create a RouteEventSource via a RouteEventSourceName (the RouteMeasurePointProperties and the RouteLocatorName are already created). These values are set using IRouteEventSourceName.
[Java]
try{
    //Get the objects from somewhere.
    IName pName = null;
    IRouteEventProperties pREProperties = null;
    IRouteLocatorName pRtLocatorName = null;

    IRouteEventSourceName pRESN = new RouteEventSourceName();
    pRESN.setEventTableNameByRef(pName);
    pRESN.setEventPropertiesByRef(pREProperties);
    pRESN.setRouteLocatorNameByRef(pRtLocatorName);

    IName pName1 = new INameProxy(pRESN);
    IRouteEventSource pRES = new IRouteEventSourceProxy(pName1.open());

}

catch (IOException ex){
    ex.printStackTrace();
}
Because a RouteEventSource is a subclass of a feature class, it can be used anywhere a feature class can be used. For example, a RouteEventSource can act as the basis of a feature layer in ArcMap and its attributes can be edited with the editing tools in ArcMap.
There may be limitations imposed by the event table—for example, you cannot edit a feature class created from a delimited text file table since the editor does not allow text files to be edited directly.
In a RouteEventSource, there is one feature for every row of the original event table. Sometimes, the features have empty shapes because the event could not be located. Other times, an event can only be partially located (happens for line events only). See the following illustration:
 

IEventSourceErrors

IEventSourceErrors exposes methods that allow you to determine the locating errors of events. See the following illustration:
The following code example uses IEventSourceErrors.GetErrors to create an enumeration of the event rows that could not be located:
[Java]
public void testGetErrors(IRouteEventSource pRES)throws IOException{
    IRow[] pRow = null;
    int[] LocError = null;
    IEventSourceErrors pESErrors = new IEventSourceErrorsProxy(pRES);
    IEnumEventError pEnum = pESErrors.getErrors();
    pEnum.next(pRow, LocError);
    do{
        switch (LocError[0]){
            case 0:
                System.out.println(pRow[0].getOID() + ":No error");
                break;
            case 1:
                System.out.println(pRow[0].getOID() + ":Invalid route ID");
                break;
            case 2:
                System.out.println(pRow[0].getOID() + ":Invalid measure");
                break;
            case 3:
                System.out.println(pRow[0].getOID() + ":Can't find route");
                break;
            case 4:
                System.out.println(pRow[0].getOID() + ":Route's shape is empty");
                break;
            case 5:
                System.out.println(pRow[0].getOID() + 
                    ":Can't find location along route");
                break;
            case 6:
                System.out.println(pRow[0].getOID() + 
                    ":Can't find extent along route");
                break;
            case 7:
                System.out.println(pRow[0].getOID() + ":From-measure partial match");
                break;
            case 8:
                System.out.println(pRow[0].getOID() + ":To-measure partial match");
                break;
            case 9:
                System.out.println(pRow[0].getOID() + 
                    ":Route's measures are not set");
                break;
            case 10:
                System.out.println(pRow[0].getOID() + 
                    ":Route is not capable of storing measures");
                break;
            case 11:
                System.out.println(pRow[0].getOID() + 
                    ":From-measure and to-measure partial match");
                break;
            default:
                System.out.println(pRow[0].getOID() + 
                    ":Non-typical locating error - " + LocError[0]);
        }
        pEnum.next(pRow, LocError);
    }
    while (pRow != null);
}

RouteLayerExtension

RouteLayerExtension is a helper class for dynamic segmentation in the ArcMap user interface. Every feature layer has zero or one associated RouteLayerExtension object. When a new feature layer is added in ArcMap, its associated feature class geometry definition is inspected to see whether IGeometryDef.GetGeometryType = esriGeometryPolyLine and IGeometryDef.isHasM = true. If both of these criteria are met (the layer is not based on linear route events), a RouteLayerExtension is attached to the layer. However, if you are creating feature layers that will not be added to an ArcMap document, attach a RouteLayerExtension if you want to use its services later in your application.

IRouteLayerExtension

Use IRouteLayerExtension to set the route identifier field name for the route feature class. The other methods on this interface are used by the Add Route Events and the Identify Route Locations dialog boxes to automatically populate certain parameters. See the following illustration:
 

Route and event geoprocessing

You need route data before starting a linear referencing project. This data may not exist, may exist but without the appropriate measure system defined, or may exist in a format you do not want to use.
A route is any linear feature that has a unique identifier and measurement system stored with it. Routes can be stored in coverages, shapefiles, and personal, file, or ArcSDE geodatabases. See the following illustration:

RouteMeasureCreator

Use RouteMeasureCreator to create routes stored in a shapefile and personal, file, or ArcSDE geodatabase. A RouteMeasureCreator merges linear features that share a common identifier and sets the measure values. See the following illustration:

IRouteMeasureCreator2

IRouteMeasureCreator2 inherits from IRouteMeasureCreator and exposes the necessary methods and properties to create route feature classes. You can specify an InputFeatureClass or an InputFeatureSelection. InputFeatureSelection creates routes from a portion of the features in your input feature class. The input line features are merged on InputRouteIDFieldName. See the following illustration:
The CreateUsingCoordinatePriority2 method is used when the route measures on the input line features are not known. This method generates the measures by accumulating the digitized length or by accumulating a numeric attribute value of the input features.
If you use digitized length, the units of the output route measures will be the same as the coordinate system of the output geometry definition's spatial reference (feet, meters, and so on). To use the digitized length, pass an empty string for the LengthFieldName parameter.
With CreateUsingCoordinatePriority2, you control the direction measures are assigned to the routes by specifying the coordinate priority of the starting measure. The coordinate priority can be set using the values in the esriMSeedingCorner enumeration: esriMSeedingUpperLeft, esriMSeedingBottomLeft, esriMSeedingUpperRight, or esriMSeedingBottomRight. These options are determined by placing the minimum bounding rectangle around the input features that are going to be merged to create one route. See the following illustration:
Routes with multiple disjointed parts are supported. A route representing a road, for example, may have the same name on either side of a river. For situations like this, you can choose to ignore spatial gaps between parts when using CreateUsingCoordinatePriority2. If you choose to ignore spatial gaps, route measures will be continuous when a disjointed route is created. If you want the spatial gap incorporated in the measures, the gap distance is the straight line distance between the endpoints of the parts. The units of the gap will be the coordinate system of the output geometry definition's spatial reference, which may or may not be the same as the measure units. See the following illustration:
The CreateUsing2Fields2 method is used when measure values exist as attributes of the input linear features. That is, two attributes exist that represent from- and to-measure information for the input lines. When using this method, it is important to orient each input linear feature in the direction of increasing measure to prevent routes that have measures that do not always increase. See the following illustration:
 

RouteMeasureCalibrator

When route measures are inaccurate, events will not be located properly. It is possible to adjust route measures to correspond with known measure locations using a RouteMeasureCalibrator. A RouteMeasureCalibrator adjusts route measures by reading measure information stored as an attribute in a point feature class. Each point falls on the particular route it calibrates or within a given tolerance. Many points can be used to calibrate a single route. See the following illustration:
During the calibration process, a new vertex is created where the calibration points intersect the route. The measure value on these new vertices corresponds to the measure value stored as a point attribute. The measure values on other preexisting route vertices can be interpolated and extrapolated. See the following illustration:

IRouteMeasureCalibrator2 

IRouteMeasureCalibrator2 inherits from IRouteMeasureCalibrator and exposes the methods and properties necessary for calibrating routes. You can specify an InputFeatureClass or an InputFeatureSelection. In putFeatureSelection gives you the ability to limit the number of points used to calibrate. The RouteLocator property should not be used. Specifying a RouteFeatureClass and RouteIDFieldName or RouteFeatureSelection and RouteIDFieldName is the recommended usage of this interface. A RouteFeatureSelection allows you to limit the routes that will be considered for calibration. See the following illustration:
For the measure value on a vertex to be interpolated or extrapolated, a calibration ratio is needed. There are two ways this ratio can be determined. The CalibrateRoutesByDistance method uses the shortest path distance between the input points. See the following illustration:
The CalibrateRoutesByMs method uses the existing measure distance between input points. This method is useful when the length to measure ratio on the input route is not consistent and you are using the calibration process to fine-tune a route's measures. See the following illustration:
Whole or partial routes can be calibrated. You can choose to interpolate between the input points, extrapolate before the input points, extrapolate after the input points, or use any combination of these three methods.
The UpdateHow parameter is given as a combination of esriGeometryUpdateMEnum values. When combining multiple values, always use the bitwise OR operator. This assures an error-free combination of the values (as long as the attempted combination is valid). Do not use the addition operator (+) to combine the values as unexpected results can occur. For example, to interpolate between the input points and to extrapolate before and after the input points, you would use 7, which equates to: esriGeometryInterpolate OR esriGeometryExtrapolateBefore OR esriGeometryExtrapolateAfter. A value of 0 will only split the input polyline and assign the Ms value to the new vertex.
When calibrating disjointed routes, you may choose to ignore the spatial gap between the parts. If you choose to ignore spatial gaps, route measures will be continuous. If you want the spatial gap incorporated in the measures, the gap distance is the straight-line distance between the endpoints of the parts. The units of the gap will be that of the coordinate system of the output geometry definition's spatial reference, which may or may not be the same as the measure units. Ignoring spatial gaps is only a valid choice when using CalibrateRoutesByDistance.

RouteMeasureGeoprocessor 

The types of event processing operations include dissolving events, concatenating events, and event overlay (line on line and point on line). Event geoprocessing is exposed via the RouteMeasureGeoprocessor class. See the following illustration:

IRouteMeasureEventGeoprocessor2

IRouteMeasureEventGeoprocessor2 inherits from IRouteMeasureEventGeoprocessor and provides access to the event geoprocessing operations. See the following illustration:

Concatenating and dissolving events

Event dissolving and event concatenating involve combining records in line event tables if they are on the same route and have the same value for specified fields. The results are written to a new line event table. The difference between dissolving and concatenating is that concatenating only combines events in situations where the to-measure of one event matches the from-measure of the next event. Dissolving events will combine events when there is measure overlap. See the following illustration:

Line-on-line overlay

A line-on-line overlay involves the overlay of two line event tables to produce a line event table. For example, you may want to take an event table that describes pavement cracking and overlay it with pavement resurfacing dates. The results of such an overlay could be used to find the characteristics of the oldest paved sections.
When performing a line-on-line overlay, the results may contain events that have no length (for example, the from- and to-measure values are the same). The IRouteMeasureEventGeoprocessor2.KeepZeroLengthLineEvents property can be used to indicate whether you want these events in your result set. See the following illustration:
 

Line-on-point overlay

A line-on-point overlay involves the overlay of a point event table with a line event table to produce a point or line event table. The intersection of a point and line event table produces a point event table. The union of a point and line event table produces a line event table. See the following illustration:
 

Point-on-point overlay

The following illustration shows point-on-point overlay:
 

RouteLocatorOperations

The RouteLocatorOperations class computes the intersection of input features (point, line, or polygon) and route features, then writes the route and measure information to a new event table. The new table can be dBASE or personal, file, and ArcSDE geodatabase. See the following illustration:
 

IRouteLocatorOperations2

The IRouteLocatorOperations2 interface inherits from IRouteLocatorOperations and provides access to the methods that allow features to be located along routes. You can specify an InputFeatureClass or an InputFeatureSelection. InputFeatureSelection gives you the ability to limit the number of features to be located. The RouteLocator property should not be used. Specifying a RouteFeatureClass and RouteIDFieldName or RouteFeatureSelection and RouteIDFieldName is the recommended usage of this interface. A RouteFeatureSelection allows you to limit the routes that will be considered for locating. See the following illustration:
 

Locating line features

The LocateLineFeatures method determines the route and measure information where the lines intersect with routes. This intersection is based on a specified cluster tolerance that represents the maximum tolerated distance between the input lines and the target routes. This method should not be thought of as a conflation tool and large cluster tolerances should be avoided. Always use the smallest cluster tolerance possible to achieve the best results. When using this method, the OutputProperties should be for line events (RouteMeasureLineProperties). See the following illustration:
 

Locating point features

The LocatePointFeatures method determines the route and measure information where the points intersect with routes. This intersection is based on a search radius, which defines how far around each point a search will be done to find a target route. When using this method, the OutputProperties should be for point events (RouteMeasurePointProperties).
The LocatePointEvents method represents a variation of the LocatePointFeatures algorithm and is designed specifically to work on point events. When using this method, the OutputProperties should be for point events (RouteMeasurePointProperties). See the following illustration:
 

Locating polygon features

The LocatePolygonFeatures method determines the route and measure information where the polygons intersect with routes. When using this method, the OutputProperties should be for line events (RouteMeasureLineProperties). See the following illustration:
 

Hatching

Hatching is a type of labeling designed to post and label hatch marks or symbols at a regular interval along measured linear features. Hatching can be used for distance-based and nondistance-based measures. Distance-based measures include kilometers, miles, feet, and meters. Nondistance-based measures include seismic shot point numbers where measure values generally increase in even intervals based on a nominal distance. See the following illustration:
 

HatchLayerExtension

Hatching is exposed via the HatchLayerExtension class. Every feature layer has zero or one associated HatchLayerExtension object. When a new feature layer is added in ArcMap, its associated feature class' geometry definition is inspected to determine if IGeometryDef.GetGeometryType = esriGeometryPolyLine and IGeometryDef.isHasM = true (includes RouteEventSource objects based on linear event tables).
If both criteria are met, a HatchLayerExtension is attached to the layer. If you are creating feature layers that will not be added to an ArcMap document, attach a HatchLayerExtension. See the following illustration:

IHatchLayerExtension

IHatchLayerExtension controls the properties of the HatchLayerExtension. To display hatches on a layer, there must be at least one HatchClass associated with the HatchLayerExtension. A HatchLayerExtension has one associated HatchClass when it is created. You can manipulate the properties of this HatchClass or you can remove it (RemoveClass or RemoveAll) and add another (AddClass). See the following illustration:
 
The following code example shows how to attach a HatchLayerExtension to a new feature layer:
[Java]
try{
    IWorkspaceFactory pWorkspaceFactory = new ShapefileWorkspaceFactory();
    IWorkspace pWorkspace = pWorkspaceFactory.openFromFile("d:/data/dyndata", 0);
    IFeatureWorkspace pFeatureWorkspace = new IFeatureWorkspaceProxy(pWorkspace);
    IFeatureLayer pFeatureLayer = new FeatureLayer();
    IFeatureClass pFeatureClass = pFeatureWorkspace.openFeatureClass("roads_hwy");
    pFeatureLayer.setFeatureClassByRef(pFeatureClass);
    pFeatureLayer.setName(pFeatureLayer.getFeatureClass().getAliasName());
    ILayerExtensions pLayerExt = new ILayerExtensionsProxy(pFeatureLayer);

    IHatchLayerExtension pHatchExt = new HatchLayerExtension();
    //pHatchClass is created elsewhere.
    IHatchClass pHatchClass = null;
    pHatchExt.addClass("", pHatchClass);
    pLayerExt.addExtension(pHatchExt);
}

catch (Exception e){
    e.printStackTrace();
}
A HatchLayerExtension can have more than one HatchClass because it is useful to hatch different features in different ways (IHatchClass.GetFilter). For example, you may want to hatch only major highways and leave local roads and collector roads unhatched. It is also useful to hatch the same features in different ways, depending on the map's scale (IHatchClass.GetMaximumScale and IHatchClass.GetMinimumScale). For example, you may want to leave features unhatched when zoomed out to a full extent, then have them hatched when zoomed in to a certain scale threshold.

HatchDefinition

A HatchClass has a HatchTemplate. Each HatchTemplate is composed of one or more HatchDefinition objects. See the following illustration:
A HatchDefinition defines the properties of the hatches. There are two kinds of HatchDefinition: HatchMarkerDefinition and HatchLineDefinition.

How hatching works

The easiest way to understand the HatchClass and HatchDefinition classes is to use a ruler analogy. On a ruler, there is a series of vertical lines or hatches separated by a regular interval. For example, on a centimeter (cm) ruler, the hatches are typically spaced every millimeter (mm). One millimeter is 1/10 of a centimeter; therefore, the hatch interval is 0.1. Not all hatches on a ruler are the same—some are longer than others and some have text, while others do not.
On a centimeter ruler, hatches placed every millimeter (0.1 cm) are the shortest and hatches placed every five millimeters (0.5 cm) are longer. Hatches placed every 10 millimeters (1 cm) are the longest. The longest hatches typically have text to indicate the measure value.
In the following illustration, the ruler is a HatchClass. It is a container for three HatchDefinition objects. Each HatchDefinition is placed at a multiple of the hatch interval (IHatchClass.SetHatchIntervalByRef). The longest hatches are placed every 0.1 by 10 measure units. The second longest hatches are placed every 0.1 by 5 measure units. The shortest hatches are placed every 0.1 by 1 measure units. When placed on a map, hatch definitions in a single hatch class will not draw on top of one another.
Imagine that you have linear features whose measures are in miles. You want to place a hatch every quarter of a mile. This is a hatch interval of 0.25. Further, you want the hatches placed every 0.25, 0.5, and 1 mile to look different (different length and different color). You want the hatches every mile to have text. Lastly, you want hatches at the ends of the feature. These end hatches look different than all other hatches and have text.
The following illustration shows conceptually how hatching works in this scenario:

Ways to control how hatches display

There are many ways to control how hatches display on a map by using the methods on the IHatchClass, IHatchTemplate, IHatchDefinition, and IHatchLineDefinition interfaces. See the following illustration:
Use IHatchClass to set properties that are specific to the data being hatched. As such, many of the properties on this interface allow data to be derived from a field or can be a specific value.
The most important property on IHatchClass is HatchInterval, which specifies in measure units where hatches display on a line (hatches can also be placed only at the route ends; in this case, do not specify a hatch interval).
All of the hatch definitions in a hatch class can be offset by the same amount using the LateralOffset property. Offsets are specified in the units of a line feature class coordinate system (for example, feet or meters) or by the settings in IHatchTemplate.SetDisplayUnits and IHatchTemplate.SetConvertUnits; however, each individual hatch definition can also have its own offset (IHatchDefinition.SetOffset). See the following illustration:
Hatching can start at a measure location other than the low measure (StartRange) of a route and can finish at a location other than the high measure (EndRange) of a route. See the following illustration:
 

HatchInputValue class

HatchInputValue is a helper class for many methods on the IHatchClass interface. For many hatching properties, you may want to retrieve values from one of the feature's attributes or you may want to use predefined values. See the following illustration:
The following code example shows how to create a HatchClass and set some of its more important properties:
[Java]
try{
    IHatchClass pHatchClass = new HatchClass();

    IHatchInputValue pHatchInput1 = new HatchInputValue();
    pHatchInput1.setValue(new Integer(100));
    pHatchClass.setHatchIntervalByRef(pHatchInput1);
    IHatchInputValue pHatchInput2 = new HatchInputValue();
    pHatchInput2.setField("MMIN");
    pHatchClass.setStartRangeByRef(pHatchInput2);
    IHatchInputValue pHatchInput3 = new HatchInputValue();
    pHatchInput3.setField("MMAX");
    pHatchClass.setEndRangeByRef(pHatchInput3);
    IHatchInputValue pHatchInput4 = new HatchInputValue();
    pHatchInput4.setValue(new Integer(50));
    pHatchClass.setLateralOffsetByRef(pHatchInput4);
}

catch (Exception e){
    e.printStackTrace();
}

IHatchTemplate

Hatching templates can be stored in esriLocationUI.HatchStyleGalleryClass. Since the properties on IHatchClass can be data specific, they are not saved when you add items to a HatchStyleGalleryClass. See the following illustration:
Use IHatchTemplate to set properties that are generic to all hatches in a HatchClass. These properties are not data specific. As such, these are the properties that do get saved when you store hatches in a HatchStyleGalleryClass.
When a feature's geometry has multiple parts, it is possible to apply hatches to the feature as a whole or to each part individually by setting SetHatchByPart to true. See the following illustration:
By default, the placement of hatches is adjusted to the hatch interval—in cases where a line's low measure is not divisible by the interval, the first hatch will be placed at the first measure value that is divisible by the hatch interval. For example, a line whose measures range from 1.1 to 5.2 will have its first hatch placed at 1.25 when the hatch interval is 0.25. This behavior can be turned off by setting SetStartAtIntervalMultiple to false. End hatch definitions are not affected by this property and are not shown in the following illustration:
When a feature's high measure is not divisible by the hatch interval and an end hatch definition has been defined, it is possible to get two hatches very close to or on top of one another. To avoid this, specify an EndHatchDrawingTolerance, which informs the hatching algorithm to not place hatches when they fall within the tolerance of the end hatch. The end hatch tolerance is specified in route measure units and its value is typically set to a value that is less than the hatch interval. See the following illustration:

As previously discussed, a HatchDefinition defines the properties of the hatches. There are two kinds of HatchDefinition: HatchMarkerDefinition and HatchLineDefinition. See the following illustration:
Use IHatchDefinition to specify the properties that are common to marker and line hatches. See the following illustration:
Each hatch definition can be displayed to the left, centered on, or to the right of a feature by setting the Alignment property. When set to center, hatches will be labeled to the left of the feature. See the following illustration:
Hatch text is flipped as the direction of the feature changes to make the text more readable. This can be turned off using AdjustTextOrientation, which allows the text to orient in the direction of increasing measure. See the following illustration:
A hatch definition will be labeled with the measure value when the TextSymbol property has been set. The number of decimal places is controlled by the DisplayPrecision property. It is possible to add a prefix or a suffix to the measure value.
The following code example adds the suffix km to every hatch in the HatchDefinition (pay particular attention to the TextDisplay and Suffix properties):
[Java]
try{
    IHatchDefinition pHatchDef = new HatchLineDefinition();
    //Get or set the symbols from somewhere.
    ILineSymbol pLineSymbol = null;
    ITextSymbol pTextSymbol = null;
    pHatchDef.setHatchSymbolByRef(new ISymbolProxy(pLineSymbol));
    pHatchDef.setTextDisplay
        (com.esri.arcgis.location.esriHatchTextDisplay.esriHatchTDPrefixSuffix);
    pHatchDef.setTextSymbolByRef(pTextSymbol);
    pHatchDef.setSuffix("km");
    pHatchDef.setDisplayPrecision(0);

}

catch (Exception e){
    e.printStackTrace();
}
For certain applications the ability to add a prefix or suffix is not enough. For these applications, it is possible to use VBScript or JScript to specify a function that will be evaluated. This function must be called FindLabel and at the very least, the esri__measure value must be passed in (there are two underscore characters in esri__measure). Fields from the layer being hatched can also be passed to the FindLabel function and are enclosed in square brackets [], regardless of the data type.
In the following code example, the FindLabel function sets a hatch's label to be an empty string when the measure value passed in (esri__measure) is within 25 measure units of the value stored in the MMax field. Otherwise, it appends the km suffix to the measure value. Pay particular attention to the TextDisplay, ExpressionParserEngine, ExpressionSimple, and Expression properties.
[Java]
try{
    IHatchDefinition pHatchDef = new HatchLineDefinition();
    //Get or set the symbols from somewhere.
    ILineSymbol pLineSymbol = null;
    ITextSymbol pTextSymbol = null;
    pHatchDef.setHatchSymbolByRef(new ISymbolProxy(pLineSymbol));
    pHatchDef.setTextSymbolByRef(pTextSymbol);
    pHatchDef.setTextDisplay
        (com.esri.arcgis.location.esriHatchTextDisplay.esriHatchTDExpression);
    pHatchDef.setExpressionSimple(false);
    pHatchDef.setExpressionParserEngine
        (com.esri.arcgis.location.esriHatchExpressionEngine.esriHatchVBScriptEngine);
    // pHatchDef.setExpressionParserEngine(
    //         com.esri.arcgis.location.esriHatchExpressionEngine.esriHatchJScriptEngine);
    StringBuffer sb = new StringBuffer();
    sb.append("Function FindLabel (esri__measure, [MMax]) & vbCrLf &");
    sb.append("mmax = [MMax] & vbCrLf &");
    sb.append("m = esri__measure & vbCrLf &");
    sb.append("If (mmax - m) <= 25 Then & vbCrLf &");
    sb.append("FindLabel =   \"\"\"\" & vbCrLf &");
    sb.append("Else & vbCrLf &");
    sb.append("FindLabel = CStr(Round(m, 1)) & \"\" km\"\" & vbCrLf &");
    sb.append("End If & vbCrLf &");
    sb.append("End Function");
    pHatchDef.setExpression(sb.toString());

}

catch (Exception e){
    e.printStackTrace();
}
Each HatchTemplate can have an EndHatchDefinition. An end hatch definition pays no attention to the specified hatch interval, but draws hatch marks at the low and high measure of a linear feature. For cases in which hatches get placed too close together near the end of a feature, it is possible to specify an EndHatchDrawingTolerance, which prevents certain hatches from drawing if they are within the tolerance (specified in measure units) of an end hatch. A HatchTemplate can only have one end hatch definition.
Use IHatchLineDefinition to specify the properties that are specific to line hatches. At the very least, always set the Length property when dealing with line hatches.
The length is specified in the units of the coordinate system of the route feature class spatial reference or by the settings IHatchTemplate.SetDisplayUnits and IHatchTemplate.SetConvertUnits. See the following illustration:
By default, line hatches are drawn perpendicular to the feature. It is possible to specify a SupplementalAngle that gets added to the calculated angle. See the following illustration: