Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I was wondering if there is a way to update a column in MapInfo with the digitised line direction. I have two TAB files, one is complete lines and the other is sections of the same lines (both have a unique ID). I was wondering if it would be possible to add a column in both files with the direction of the line so I can check if the directions are identical, e.g:

enter image description here

Thanks, Alan

share|improve this question
    
this question is incomplete as it stands, We need to know what the direction refers to. All lines have an inherent direction (digitized) from node, to node. you can create topology on lines which then gives them cost. Cost can be one way, two way, or blocked. If these are just lines that you want to compare, and you are not doing network analysis, or routing on now, please explain further your idea for the use of direction. –  Brad Nesom Jun 20 '13 at 13:29
    
It would be digitised direction. Data is being collected between the chainages and I have to ensure both lines have the same direction to ensure data delivered is in the right location compared to the original full sections. –  Alan Carr Jun 20 '13 at 13:39
    
please edit your question with appropriate descriptions. just push the edit button. –  Brad Nesom Jun 20 '13 at 13:41

2 Answers 2

To my knowledge there is no MapBasic function returning the order of digitalization. You line direction have several direction, so I would it digitalization order instead.

You could in MapBasic code a program checking if the end point of a line is north, west, east or south of the start point. And then update your column with the text north, west, east or south.

Not sure about complex lines, but worth a test.

share|improve this answer

I would run they each of the individual segments and for each find the matching node in the complex polyline for the start as well as the end node of the section.

Now you can check if the end node number is larger than the start node number. If so the line direction of the section is the same as the direction of the polyline.

If not, the direction is reverted.

Here's some code that can help you find the node number within a polyline/polygon with only one segment:

'******************************
Function OBJFindNode(     ByVal oObj As Object      'The object (polyline or polygon) to search in, only the first segment of the object will be searched
                        , ByVal oNode As Object     'Node position to look for
                        , ByVal fTolerance As Float 'Search tolerance, in meters, distance is measured using Cartesian calculation
                        ) As Integer                'Returns the first matching node number, or 0 if no found

Dim nSegm, nNode As Integer

OnError GoTo ErrorOccured

OBJFindNode = 0

If OBJFindSegmentAndNode(oObj, oNode, fTolerance, nSegm, nNode) Then
    If nSegm = 1 Then
        OBJFindNode = nNode
    End If
End If

Exit Function
'-------------------------
ErrorOccured:
    Note Err() + " " + Error$() + ": OBJFindNode"
End Function

'************************************
Function OBJFindSegmentAndNode( ByVal oObj As Object        'The object (polyline or polygon) to search in
                              , ByVal oNode As Object       'Node position to look for
                              , ByVal fTolerance As Float   'Search tolerance, in meters, distance is measured using Cartesian calculation
                              , nSegmentFound As Integer    'The Segment number where the node was found
                              , nNodeFound As Integer       'The matching node number
                                  ) As Logical              'Returns TRUE if a matching node was found, otherwise FALSE

Dim nSegm, nNode As Integer,
    fNodeX, fNodeY, fX, fY, fDistance As Float

OnError GoTo ErrorOccured

OBJFindSegmentAndNode = FALSE

If NOT ObjectInfo(oObj, OBJ_INFO_TYPE) IN (OBJ_TYPE_PLINE, OBJ_TYPE_REGION) Then
    Exit Function
End If

fNodeX  = CentroidX(oNode)
fNodeY  = CentroidY(oNode)

For nSegm = 1 To ObjectInfo(oObj, OBJ_INFO_NPOLYGONS)
    For nNode = 1 To ObjectInfo(oObj, OBJ_INFO_NPOLYGONS + nSegm)
        fX  = ObjectNodeX(oObj, nSegm, nNode)
        fY  = ObjectNodeY(oObj, nSegm, nNode)
        fDistance   = CartesianDistance(fNodeX, fNodeY, fX, fY, "m")
        If fDistance <= fTolerance Then
           nSegmentFound    = nSegm
           nNodeFound   = nNode
           OBJFindSegmentAndNode = TRUE
           Exit Function
        End If
   Next     'nNode
Next        'nSegm

Exit Function
'-------------------------
ErrorOccured:
    Note Err() + " " + Error$() + " OBJFindSegmentAndNode"
End Function

'******************************
Function OBJFindNodeBinary(   ByVal oObj As Object      'The object (polyline or polygon) to search in, only the first segment of the object will be searched
                            , ByVal oNode As Object     'Node position to look for
                            , ByVal fTolerance As Float 'Search tolerance, in meters, distance is measured using Cartesian calculation
                            , ByVal nOffset As Integer  'Offset of 1st node in polyline based on original
                            ) As Integer                'Returns the first matching node number, or 0 if no found

Dim objLow, objHigh As Object,
    nPnts, nNode, nMid As Integer

OnError GoTo ErrorOccured

OBJFindNodeBinary = 0

nPnts = ObjectInfo(oObj, OBJ_INFO_NPNTS)

If nPnts < 100 Then
    nNode = OBJFindNode( oObj, oNode, fTolerance)
    If nNode > 0 Then
        OBJFindNodeBinary = (nNode + nOffset)
    End If
    Exit Function
End If

'Determine the middle point
nMid = nPnts \ 2 + nPnts Mod 2

'Start with the lower half
objLow = ExtractNodes( oObj, 1, 1, nMid, FALSE)
If oNode Within CartesianBuffer(MBR(objLow), 25, fTolerance, "m") Then
    nNode = OBJFindNodeBinary(objLow, oNode, fTolerance, nOffset)
    OBJFindNodeBinary = nNode
Else
    ' Forget this branch
    nNode = 0
End If

' If we couldn't find it in the lower, then check the upper half
If nNode = 0 Then
    objHigh = ExtractNodes(oObj, 1, nMid + 1, nPnts, FALSE )
    If oNode Within CartesianBuffer(MBR(objHigh), 25, fTolerance, "m") Then
        nNode = OBJFindNodeBinary( objHigh, oNode, fTolerance, nOffset + nMid)
    Else
        ' Forget this branch
        nNode = 0
    End If
End If

OBJFindNodeBinary = nNode

Exit Function
'-------------------------
ErrorOccured:
    Print Err() + " " + Error$() + " OBJFindNodeBinary: nNode: " + nNode
End Function

The fundemental structure of the Binary search function has been made by Bill Thoen who shared it on MapInfo-L more than a year ago.

This is how to use the code above:

Dim oPolyline, oPoint, oLine As Object,
    nOrder, nTolerance, nNode1, nNode2, nRowID As Integer

nTolerance = 0.2 'meters

Set CoordSys Table TABLE_WITH_LINES

Fetch First From TABLE_WITH_POLYLINES
oPolyline = TABLE_WITH_POLYLINES.OBJ

Fetch First From TABLE_WITH_LINES
Do Until EOT(TABLE_WITH_LINES)
    oLine = TABLE_WITH_LINES.OBJ
    nRowID = TABLE_WITH_LINES.ROWID 

    oPoint = CreatePoint(ObjectGeography(oLine, OBJ_GEO_LINEBEGX), ObjectGeography(oLine, OBJ_GEO_LINEBEGY))
    nNode1  = OBJFindNodeBinary(oPolyline, oPoint, 0.2, 0)

    oPoint = CreatePoint(ObjectGeography(oLine, OBJ_GEO_LINEENDX), ObjectGeography(oLine, OBJ_GEO_LINEENDY))
    nNode2  = OBJFindNodeBinary(oPolyline, oPoint, 0.2, 0)

    nOrder = 0
    If nNode1 = 0 or nNode2 = 0 Then
        'First of last point could not be matched to a node within the tolerance given
    ElseIf nNode1 < nNode2 Then
        nOrder = 1
    ElseIf nNode1 > nNode2 Then
        nOrder = -1
    End If

    Update TABLE_WITH_LINES
        Set Direction = nOrder
        Where ROWID = nROWID

    Fetch Next From TABLE_WITH_LINES
Loop

Notice that in the sample above I'm expected you to only have one polyline. If that's not the case you need to figure out how to link the current line to the matching polyline. If the line table holds a reference ID for the polyline table, you can use this.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.