How to add measure values to a feature class


Once a feature class exists on disk, you cannot change it's spatial reference or its geometry definition. If you need to change one of these, you need to re-load your data.
In order to perform Dynamic Segmentation, you need a feature class whose geometry type is PolyLine and is able to store measures (Ms).
If you have PolyLine data that is not capable of storing measures, you will need to convert it.
This code demonstrates how to use the FeatureDataConvertor to create a new feature class that can store measure values. If your input is shapefile, the results will be shapefile in the same workspace. If your input is an ArcSDE feature class, your result will be an ArcSDE feature class in the same workspace. This code will not work for coverage data.
In the code below, you are asked to specify a minimum M value (dMMin) and a maximum m value (dMMax). For Geodatabases, these values represent the allowable range of M values. These settings have no effect on shapefiles, so you can put 0 (or any other number) for these.
The resulting feature class will have all the M values set to NaN (not a number). There are a variety of ways to set the measure values. For example, see the Route Editing Extension sample.

How to use

  1. Paste the code into VBA.
  2. Write code that calls ConvertAndAddMDomain
[VBA]
Public Sub ConvertAndAddMDomain(pInputFC As IFeatureClass, sOutDSName As String, _
                                sOutFCName As String, dMMin As Double, dMMax As Double)
    
    '+++ Get the input workspace and feature class name object
    Dim pOutWS As IWorkspace '+++ write output to the same workspace as the input
    Dim pTempDS As IDataset
    Dim pInFCName As IFeatureClassName
    Set pTempDS = pInputFC
    Set pOutWS = pTempDS.Workspace
    Set pInFCName = pTempDS.FullName
    
    '+++ Make sure the input is not a coverage
    If TypeOf pOutWS Is IArcInfoWorkspace Then
        MsgBox "The FeatureDataConvertor object cannot be used " & vbCrLf & _
            "to create coverage route systems!!!", vbExclamation, "ConvertAndAddMDomain"
        Exit Sub
    End If
    
    '+++ Create a feature datset name object for the output feature dataset
    '+++ (this is only applicable when writing to Personal or ArcSDE Geodatabases)
    Dim pOutPropset As IPropertySet
    Set pOutPropset = pOutWS.ConnectionProperties
    Dim pOutWSName As IWorkspaceName
    Set pOutWSName = New WorkspaceName
    pOutWSName.ConnectionProperties = pOutPropset
    Select Case pOutWS.Type
        Case esriLocalDatabaseWorkspace
            pOutWSName.WorkspaceFactoryProgID = "esriDataSourcesGDB.AccessWorkspaceFactory.1"
        Case esriRemoteDatabaseWorkspace
            pOutWSName.WorkspaceFactoryProgID = "esriDataSourcesGDB.SdeWorkspaceFactory.1"
        Case Else
            pOutWSName.WorkspaceFactoryProgID = "esriDataSourcesFile.ShapefileWorkspaceFactory.1"
    End Select
    Dim pOutFeatDSName As IFeatureDatasetName
    If Not Len(sOutDSName) = 0 Then
        If Not pOutWS.Type = esriFileSystemWorkspace Then
            Set pOutFeatDSName = New FeatureDatasetName
            Dim pOutDSName As IDatasetName
            Set pOutDSName = pOutFeatDSName
            Set pOutDSName.WorkspaceName = pOutWSName
            pOutDSName.Name = sOutDSName
        End If
    End If
    
    '+++ Create the new output FeatureClassName object
    Dim pOutFCName As IFeatureClassName
    Dim pOutDSName2 As IDatasetName
    Set pOutFCName = New FeatureClassName
    Set pOutDSName2 = pOutFCName
    Set pOutDSName2.WorkspaceName = pOutWSName 'esp. necessary when pOutDSN is Nothing
    pOutDSName2.Name = sOutFCName
    
    
    '+++ Get the fields for the input feature class. Note that we do not need to run
    '+++ them through the field checker because we are writing to the same workspace
    Dim pOutFlds As IFields
    Set pOutFlds = pInputFC.Fields
    
    '+++ Find the geometry field
    Dim i As Long
    Dim sGeoField As String
    Dim pGeoField As IField
    sGeoField = pInputFC.ShapeFieldName
    i = pOutFlds.FindField(sGeoField)
    Set pGeoField = pOutFlds.Field(i)
    
    '+++ Get the geometry field's geometry definition and set HasM and the
    '+++ spatial reference (remember a feature class can be used in DynSeg when (i)
    '+++ its geometry type is PolyLine and (ii) it's geometry definition HasM)
    Dim pOutGeoDef As IGeometryDef
    Dim pOutGeoDefEdit As IGeometryDefEdit
    Set pOutGeoDef = pGeoField.GeometryDef
    Set pOutGeoDefEdit = pOutGeoDef
    pOutGeoDefEdit.HasM = True
    
    Dim pOutSRef As ISpatialReference
    Set pOutSRef = pOutGeoDef.SpatialReference
    pOutSRef.SetMDomain dMMin, dMMax '+++ this actually does nothing for shapefiles
    Set pOutGeoDefEdit.SpatialReference = pOutSRef
    
    '+++ Now use IFeatureDataConverter::Convert to create the output FeatureDataset and
    '+++ FeatureClass.
    Dim pDataConv As IFeatureDataConverter
    Dim pEnum As IEnumInvalidObject
    Set pDataConv = New FeatureDataConverter
    Set pEnum = pDataConv.ConvertFeatureClass(pInFCName, Nothing, pOutFeatDSName, _
                pOutFCName, pOutGeoDef, pOutFlds, "", 1000, 0)
    
    '+++ Make sure pEnumvalidObject does not reject any features
    Dim pInvalidInfo As IInvalidObjectInfo
    pEnum.Reset
    Set pInvalidInfo = pEnum.Next
    While Not pInvalidInfo Is Nothing
        Debug.Print pInvalidInfo.InvalidObjectID & ": " & pInvalidInfo.ErrorDescription
        Set pInvalidInfo = pEnum.Next
    Wend
    
End Sub






Additional Requirements
  • ArcEditor at 9.0; ArcView at 9.1 forward