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.

Note: 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.

Note: 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 VB/VBA.
  2. Write code that calls ConvertAndAddMDomain
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 = "esriCore.AccessWorkspaceFactory.1"
    Case esriRemoteDatabaseWorkspace
      pOutWSName.WorkspaceFactoryProgID = "esriCore.SdeWorkspaceFactory.1"
    Case Else
      pOutWSName.WorkspaceFactoryProgID = "esriCore.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
  Set pInvalidInfo = pEnum.Next
  While Not pInvalidInfo Is Nothing
    Debug.Print pInvalidInfo.InvalidObjectID & ": " & pInvalidInfo.ErrorDescription
    Set pInvalidInfo = pEnum.Next
End Sub