M Values for points or lines

Jan 31 at 11:33 PM
I am really stuck. I have been able to create a point Shape File With X, Y, and Z Values I cannot get it to keep the M Values I am setting. Afetr creating the Shape File, I open it inside of ArcMap. It says it has Z and M but neither show up when editing. it return "NaN" for the M Value

I get the same for a multiline Shape, (I think this is how you make a polyline) except it also return a "NaN" for the Z value even though I set it.

I use the same set of coordinate points to create the line as well as the Point shape files.
Developer
Feb 1 at 7:38 AM
What version of DotSpatial do you use?

Please post the code you used to create, fill and save the shapefile.
Feb 1 at 2:59 PM
Edited Feb 1 at 3:10 PM
I am using the latest 1.9

Here is the code

Private Function CreateShapeFile(ShapeType As FeatureType, columns As ObservableCollection(Of PointColumns), ShapeFileName As String) As FeatureSet
    Try

        Dim returnval As DotSpatial.Data.FeatureSet = New FeatureSet(ShapeType)

        returnval.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984
        returnval.CoordinateType = CoordinateType.Z


        For i = 0 To columns.Count - 1
            Dim column As DataColumn = New DataColumn(columns(i).ColumnName)
            Select Case columns(i).ColumnType
                Case Is = "String"
                    returnval.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.String)))
                Case Is = "Date"
                    returnval.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.DateTime)))
                Case Is = "Double"
                    returnval.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.Double)))
            End Select
        Next
        returnval.SaveAs(String.Format("{0}", ShapeFileName), True)
        Return returnval
    Catch ex As Exception
        WriteToFile(ex.Message & ex.StackTrace)
        Return Nothing
    End Try

End Function


Private Function AddPointFeatureToShape(coords As List(Of Coordinate), columns As ObservableCollection(Of PointColumns), Optional lineF As FeatureSet = Nothing) As DotSpatial.Data.FeatureSet
    Dim pointF As New FeatureSet(FeatureType.Point)
    Try




        pointF.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984
        pointF.CoordinateType = CoordinateType.Z

        For i = 0 To columns.Count - 1
            Dim column As DataColumn = New DataColumn(columns(i).ColumnName)
            Select Case columns(i).ColumnType
                Case Is = "String"
                    pointF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.String)))
                Case Is = "Date"
                    pointF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.DateTime)))
                Case Is = "Double"
                    pointF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.Double)))
            End Select
        Next

    Catch
    End Try



    Try
        For i = 0 To coords.Count - 1
            Dim coord As Coordinate = New Coordinate(coords(i).X, coords(i).Y, coords(i).Z)
            Dim newpoint As DotSpatial.Topology.Point = New DotSpatial.Topology.Point(coord.X, coord.Y, coord.Z)
            Dim currentFeature As DotSpatial.Data.IFeature = pointF.AddFeature(newpoint)
            currentFeature.DataRow("Owner") = "THE OWNER " & i.ToString
            currentFeature.DataRow("OwnedSince") = Now.ToShortDateString
        Next




        Return pointF

    Catch ex As Exception
        WriteToFile(ex.Message & ex.StackTrace)
        Return Nothing
    End Try

End Function
When using the addpointoshape Fuinction and saving the returned featureset as the ShapeFile I get the NaN result.
Developer
Feb 2 at 8:40 AM
The only reason I see for your M beeing NaN is that you didn't add it to your features. So change
Dim newpoint As DotSpatial.Topology.Point = New DotSpatial.Topology.Point(coord.X, coord.Y, coord.Z)
to
Dim newpoint As DotSpatial.Topology.Point = New DotSpatial.Topology.Point(coords(i).X, coords(i).Y, coords(i).Z, coords(i).M)
to include M. If you didn't remove something from your function creating coord is not nessessary.

The following code creates a shapefile that contains M and Z values.
  Private Function AddPointFeatureToShape() As FeatureSet
        Dim pointF As New FeatureSet(FeatureType.Point)
        Try

            Dim coords As New List(Of Coordinate)
            coords.Add(New Coordinate(1, 2, 3, 4))
            coords.Add(New Coordinate(4, 5, 6, 7))
            coords.Add(New Coordinate(7, 8, 9, 10))


            pointF.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984
            pointF.CoordinateType = CoordinateType.Z

            For i = 0 To coords.Count - 1
                Dim newpoint As DotSpatial.Topology.Point = New DotSpatial.Topology.Point(coords(i))
                Dim currentFeature As IFeature = pointF.AddFeature(newpoint)
            Next


            pointF.SaveAs("D:\test.shp", True)

            Return pointF

        Catch ex As Exception
            MsgBox(ex.Message & ex.StackTrace)
            Return Nothing
        End Try

    End Function
Feb 2 at 8:21 PM
Yea I dont know how I missed that. If you could also advise me, I am trying to produce the same thing with a LineString Feature.

I basically am getting the same result. The Features are there, They show that they support Z and M, but during editing in ArcMap, those values are NaN.

I used the same approach from the Function you showed. Being constructed a little differntly, I also followed the "DotSpatial_4_Attributes Table.docx" document and modified it to what I though was correct.

Private Function AddPolyLineFeatureToShape(coords As List(Of Coordinate), columns As ObservableCollection(Of PointColumns)) As FeatureSet
   dim lineF As FeatureSet = New FeatureSet(FeatureType.Line)

    Try

        lineF.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984
        lineF.CoordinateType = CoordinateType.Z

        For i = 0 To columns.Count - 1

            Dim column As DataColumn = New DataColumn(columns(i).ColumnName)
            Select Case columns(i).ColumnType

                Case Is = "String"
                    lineF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.String)))

                Case Is = "Date"
                    lineF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.DateTime)))

                Case Is = "Double"
                    lineF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.Double)))

            End Select

        Next


    Dim lineArray As New List(Of Coordinate)
    Dim lineGeometry As LineString = New LineString(lineArray)
    Dim lineFeature As DotSpatial.Data.IFeature = lineF.AddFeature(lineGeometry)
    lineFeature.Coordinates.Add(New Coordinate(coords(0).X, coords(0).Y, coords(0).Z, coords(0).M))
    lineFeature.DataRow("Owner") = "THE OWNER"
    lineFeature.DataRow("OwnedSince") = Now.ToShortDateString
    Dim existingFeature As DotSpatial.Data.IFeature = lineF.Features(lineF.Features.Count - 1)

    For i = 0 To coords.Count - 1
     existingFeature.Coordinates.Add(New Coordinate(coords(i).X, coords(i).Y, coords(i).Z, coords(i).M))
    Next
    If (existingFeature.Coordinates.Count >= 2) Then
      lineF.InitializeVertices()
    End If


    lineF.SaveAs("D:\test.shp", True)
    Return lineF

    Catch ex As Exception
        MsgBox(ex.Message & ex.StackTrace)
        Return Nothing
    End Try

End Function
Developer
Feb 3 at 9:01 AM
Ok. I'm not sure I understand what you're doing here:
    Dim lineArray As New List(Of Coordinate)
    Dim lineGeometry As LineString = New LineString(lineArray) // you create an empty linestring geometry
    Dim lineFeature As DotSpatial.Data.IFeature = lineF.AddFeature(lineGeometry) //you create a feature with this empty geometry
    lineFeature.Coordinates.Add(New Coordinate(coords(0).X, coords(0).Y, coords(0).Z, coords(0).M)) //you add your first coordinate to this feature

    Dim existingFeature As DotSpatial.Data.IFeature = lineF.Features(lineF.Features.Count - 1) //you get the last feature in lineF, but you already have it in lineFeature 

    For i = 0 To coords.Count - 1
     existingFeature.Coordinates.Add(New Coordinate(coords(i).X, coords(i).Y, coords(i).Z, coords(i).M)) //you add all your coordinates to existingFeature, but now it contains the first point twice
    Next
    If (existingFeature.Coordinates.Count >= 2) Then
      lineF.InitializeVertices()
    End If
If you simply want to have one LineString feature that contains all the coordinates you passed to the function, you could do it like this:
    Dim lineFeature As DotSpatial.Data.IFeature = lineF.AddFeature(New LineString(coords)) //create a new linestring feature with the given coordinates 
    lineFeature.DataRow("Owner") = "THE OWNER"
    lineFeature.DataRow("OwnedSince") = Now.ToShortDateString
    lineF.InitializeVertices()
Make sure that your LineStrings contain at least 2 different points, otherwise you'll get problems with invalid geometries.
Feb 3 at 2:57 PM
Edited Feb 3 at 3:14 PM
Wow. I made that harder than it should be. Thanks for that help.

I made the changes you showed and I still get NaN for Z and M within ArcMap. All the coordinates in the coords list have Z and M values.

Here is the code as it is now.

Private Function AddPolyLineFeatureToShape(coords As List(Of Coordinate), columns As ObservableCollection(Of PointColumns)) As DotSpatial.Data.FeatureSet
        Dim lineF As FeatureSet = New FeatureSet(FeatureType.Line)
    Try
        lineF.Projection = DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984
        lineF.CoordinateType = CoordinateType.Z
        For i = 0 To columns.Count - 1
            Dim column As DataColumn = New DataColumn(columns(i).ColumnName)
            Select Case columns(i).ColumnType
                Case Is = "String"
                    lineF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.String)))
                Case Is = "Date"
                    lineF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.DateTime)))
                Case Is = "Double"
                    lineF.DataTable.Columns.Add(New DataColumn(columns(i).ColumnName, GetType(System.Double)))
            End Select
        Next
        Dim lineFeature As DotSpatial.Data.IFeature = lineF.AddFeature(New LineString(coords))
        lineFeature.DataRow("Owner") = "THE OWNER"
        lineFeature.DataRow("OwnedSince") = Now.ToShortDateString
        lineF.InitializeVertices()
        lineF.SaveAs("D:\test.shp", True)
        Return lineF
    Catch ex As Exception
        MsgBox(ex.Message & ex.StackTrace)
        Return Nothing
    End Try

End Function
Developer
Feb 7 at 12:59 PM
Seems there is an error in DotSpatial. Have a look at issue 935. As soon as it is closed you can download the latest dlls. Then your AddPolyLineFeatureToShape should work correctly.
Feb 7 at 3:08 PM
Thanks! I really like what you guys are doing. Makes things for guys like me a lot easier.