I have lines representing curving streams (blue line in the Picture) and want to angle symbols perpendicular to the angle in their particular Locations (point features symbolized as red lines in the picture).

With Layer Properties - Symbology -> Advanced I can use a field Expression to rotate my Symbole as desired. I therefore Need to create a field in the attribute table with the correct angle-number in it which I then can sue in the field expression. Does anyone know, how I can formulate an Expression which tells me the angle the Point has to rotate to be perpendicular to the line?

I work with ArcGIS 10.2.


enter image description here

  • 1
    So, on the picture, you have only blue line (one feature)? No point feature where the 1750 is shown? Mar 3 '16 at 15:38
  • Ignore the 1750 Line, it is about the red lines (actually point Features which are symbolized as a line) who are perpendicular to the blue line Mar 3 '16 at 15:41
  • 1
    Please update your question to keep it clear, currently it might be confusing for others :) Mar 3 '16 at 15:45

There is no calculation that can do that. Fortunately this is built in to LR point event layers. Convert your lines to Routes using the Create Route tool, locate your points on the line as an event table using the Locate Features Along Route tool, then use the event table to build a point event layer using the Make Route Event Layer tool with the Angle option. If you export that layer from the Table of Contents it will become a normal point feature class that has all of your point attributes along with a LOC_ANGLE field that tells you the normal angle to the line. The angles will be Arithmetic angles (counter clockwise beginning at East). This angle can be used to rotate your symbol.

In my opinion all users that regularly do work with linear networks that have related point or line features along them should be familiar with the LR toolbox tools.

  • I tried this and it seems to work. However the angles are not totally perpendicular to the routes. In the Rotate Symbol Settings: Do I chose Arithmetic? or do I add a Field Expression? Apr 19 '16 at 13:59
  • Choose the Arithmetic angles option in the Layer Symbology Advanced settings. That option works the same way as the angles created for the event table, i.e., 0 degrees is East and the degrees increase in a counterclockwise direction. They are perpendicular between vertices, but not if they hit the angle point vertex. It will be perpendicular to one branch only. Nothing divides the angles in half at the angle point for you automatically. Apr 19 '16 at 14:31

You can do that with some arcpy.

1) You need to do the Spatial Join between the points and the lines to transfer the ID value of each line to each point.

2) Find out the closest vertex of the line and the input point.

3) Calculate the direction of this segment.

4) Update the rotation field of the points (with joined line ID).

import arcpy
import math

def GetAzimuthPolyline(firstPoint,lastPoint):
    radian = math.atan((lastPoint.X - firstPoint.X)/(lastPoint.Y - firstPoint.Y))
    degrees = radian * 180 / math.pi
    return degrees

lines_fc = r"C:\GIS\Temp\ArcGISHomeFolder\Default.gdb\_lines"
pnts_fc = r"C:\GIS\Temp\ArcGISHomeFolder\Default.gdb\_points_SpatialJoin2"

lines = [f for f in arcpy.da.SearchCursor(lines_fc,["ID","SHAPE@"],None,spatial_reference)]
pnts = [p for p in arcpy.da.SearchCursor(pnts_fc,["ID","SHAPE@"],None,spatial_reference)]

line_vertices_dict = {line[0]:line[1].getPart(0) for line in lines}

#finding out which vertex of the line is the closest to each of the
#points - to calculate direction later
nearest_vertex = dict.fromkeys([pnt[0] for pnt in pnts])
for pnt in pnts:
    vertex_tuple = line_vertices_dict[pnt[0]]
    vertex_id = 0
    for vertex in vertex_tuple:
        distance = round(pnt[1].distanceTo(vertex),2)

        if not nearest_vertex[pnt[0]]:
            nearest_vertex[pnt[0]] = ({vertex_id:distance})

        if vertex_id == 0:
            if distance < nearest_vertex[pnt[0]][vertex_id]:
                nearest_vertex[pnt[0]] = ({vertex_id:distance})

            if distance < nearest_vertex[pnt[0]].values()[0]:
                nearest_vertex[pnt[0]] = ({vertex_id:distance})
        vertex_id += 1
print nearest_vertex

#{u'A1': {0: 157.06},
#u'C3': {3: 553.08},
#u'D4': {0: 244.37},
#u'E5': {1: 271.14},
#u'B2': {1: 779.33}}

#creating a dictionary of line directions - to be used for point symbols rotation
angles_dict = {pnt[0]:
                                  [nearest_vertex[pnt[0]].keys()[0]]) for pnt in pnts}

#calculating the direction of the segment connecting the symbol point and the nearest vertex
with arcpy.da.UpdateCursor(pnts_fc,["ID","RotatField"]) as upd_cur:
    for row in upd_cur:
        row[1] = angles_dict[row[0]]

This is how it might look:

enter image description here

  • will get back to you in the end of march with my answer Mar 17 '16 at 13:27

You can do that very easy by using the NEAR-Tool from the ArcToolbox with the optional parameter "Angle" checked. Whether you add a double-field for your Angle and calculate it by subtract 90 degrees from the field NEAR_ANGLE (added from NEAR-Tool) or you use the field NEAR_ANGLE directly and subtract the 90 degrees by the Expression Builder inside the Rotate properties.

  • I forgot: There is a little problem: NEAR doesn't calculate the angle, if the point lays exactly on the line. Therefore my suggestion is to move the lines or points temporarely by a small distance before using NEAR.
    – PrHa
    Jun 26 '18 at 9:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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