Calculating angles using ArcGIS Desktop 10.2

19633
32
Jump to solution
01-21-2016 11:17 AM
BrianVann
New Contributor II

I need to find angles of streets where they intersect with roadways covering the entire state. Does anyone have a method and/or tools in mind?

0 Kudos
32 Replies
WesMiller
Regular Contributor III

Glad to here it!

0 Kudos
BrianVann
New Contributor II

Hi Wes,

It's me again with problems with the angles of roadways. I have found the tool you provided, which is pretty awesome, has the tendency to produce a point on angles that are greater than the parameters set in the model. Although  the tool does find these angles at intersections, it tends to produce some outside the parameters set. These extra points that are suppose to signify angles within the tool parameters are always located where  buffers overlap. What do you think? Can these be removed somehow via your tool?

overlappingcircles.pngThanks!

0 Kudos
WesMiller
Regular Contributor III

Did you try using a smaller buffer size? This may get the desired results.

Edit:

I just checked the model you should also change the search distance in the "Generate Near Table" tool to match the buffer size you use. Originally i used the buffer distance + 1 to make sure i was far enough out to capture the intended points.

0 Kudos
DarrenWiens2
MVP Honored Contributor

This post has been on my mind for a while, and here's what I came up with. I suspect it's quite similar to Wes' previously posted solution, but works for all license levels:

>>> import os
... fc = "myLines"
... sr = arcpy.Describe(fc).spatialReference
... radius = 50
... out_fc = r'in_memory\points'
... int_pt = r'in_memory\int_pt'
... arcpy.Intersect_analysis(fc,int_pt,output_type='POINT')
... diss_int_pt = r'in_memory\diss_int_pt'
... arcpy.Dissolve_management(int_pt,diss_int_pt,'#',[["FID","MIN"]],"SINGLE_PART")
... buff = r'in_memory\buff'
... arcpy.Buffer_analysis(diss_int_pt,buff,str(radius) + ' METERS')
... buff_line_int = r'in_memory\buff_line_int'
... arcpy.Intersect_analysis([buff,fc],buff_line_int,output_type='POINT')
... sing_buff_line_int = r'in_memory\sing_buff_line_int'
... arcpy.MultipartToSinglepart_management(buff_line_int,sing_buff_line_int)
... new_points = {}
... with arcpy.da.SearchCursor(diss_int_pt,['OID@','SHAPE@'],spatial_reference=sr) as cursor1:
...    for row1 in cursor1:
...        cent_pt = row1[1].centroid
...        angs = []
...        with arcpy.da.SearchCursor(sing_buff_line_int,'SHAPE@','\"FID_buff\" = ' + str(row1[0]),spatial_reference=sr) as cursor2:
...            for row2 in cursor2:
...                buff_pt = row2[0].centroid
...                dx = cent_pt.X - buff_pt.X
...                dy = cent_pt.Y - buff_pt.Y
...                if dx < 0 and dy <= 0:
...                    ang = math.degrees(math.atan(abs(dy/dx)))
...                if dx <= 0 and dy > 0:
...                    ang = math.degrees(math.atan(abs(dx/dy))) + 270
...                if dx > 0 and dy >= 0:
...                    ang = math.degrees(math.atan(abs(dy/dx))) + 180
...                if dx >= 0 and dy < 0:
...                    ang = math.degrees(math.atan(abs(dx/dy))) + 90
...                angs.append(ang)
...        angs.sort()
...        for i in range(1,len(angs)):
...            mid_ang = ((angs + angs[i-1])/2)
...            ang_diff = angs - angs[i-1]
...            new_x = cent_pt.X + (radius * math.cos(math.radians(mid_ang)))
...            new_y = cent_pt.Y + (radius * math.sin(math.radians(mid_ang)))
...            new_point = arcpy.PointGeometry(arcpy.Point(new_x, new_y),sr)
...            new_points[str(row1[0]) + '_' + str(i)] = [ang_diff,new_point]
...        mid_ang = (((360-angs[-1]) + angs[0])/2) - (360-angs[-1])
...        ang_diff = (360-angs[-1]) + angs[0]
...        new_x = cent_pt.X + (radius * math.cos(math.radians(mid_ang)))
...        new_y = cent_pt.Y + (radius * math.sin(math.radians(mid_ang)))
...        new_point = arcpy.PointGeometry(arcpy.Point(new_x, new_y),sr)
...        new_points[str(row1[0]) + '_0'] = [ang_diff,new_point]
... arcpy.CreateFeatureclass_management(os.path.dirname(out_fc),os.path.basename(out_fc),'POINT',spatial_reference=sr)
... arcpy.AddField_management(out_fc,'FID_buff',"LONG")
... arcpy.AddField_management(out_fc,'ANGLE',"DOUBLE")
... iCursor = arcpy.da.InsertCursor(out_fc,['SHAPE@','FID_buff','ANGLE'])
... for k,v in new_points.iteritems():
...    row = [v[1],k.split('_')[0],v[0]]
...    iCursor.insertRow(row)

WesMiller
Regular Contributor III

Darren NICE!

Does your second intersect create points where the buffers overlap see above from Brian? I told Brian to reduce the buffer size and that should work, but like you I've thought a lot about this one too. In retrospect i think i would add a select by location and just gather the points that intersect the streets and calculate from there. After looking at your code i feel like i got off easy using the near tool to grab the angles of the line and doing light math to calculate the angles.

0 Kudos
DarrenWiens2
MVP Honored Contributor

The script makes points on each buffer in isolation, so there is no influence from any other buffer. I agree that the buffer size should be as low as reasonable. You would run into problems if the buffer overlapped other intersections or parallel streets.

Good:

Bad:

BrianVann
New Contributor II

Darren,

I also thought of completing this task similar to what your image shows. It seems it should be somewhat simple; buffer points at intersections by 100 ft, convert the buffers to a line, and simply clip the arc of each resulting line where the roads intersect the circular line. Any circular line that has been clipped from a roadway line that has a arc length between the parameters of 1ft to 122.17ft (at a radius of 100ft) would be an intersection where a roadway has an intersecting roadway of less than 70 degrees. The problem I had with this method is that the process returned many arcs lengths from the buffered lines that were actually not due to the clipping function but rather due to the fact that they were not completely closed lines and thus left short arcs...

Your model looks very promising and seems a good method to use; however, I keep getting error messages when put into the python window. I haven’t much experience with python.

example: Runtime error  Traceback (most recent call last):   File "<string>", line 9, in <module>   File "c:\program files (x86) \arcgis\desktop10.2\arcpy\arcpy\management.py", line 4021, in Dissolve     raise e ExecuteError: ERROR 000369: Invalid input field(s)

Hope this makes sense...

And, thanks for the help!!

0 Kudos
BrianVann
New Contributor II

Darren,

I finally got the script to work by exporting the fc into a shapefile.

And now receiving this error message:

Runtime error  Traceback (most recent call last):   File "<string>", line 49, in <module>   File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy\management.py",

line 3052, in AddField     raise e ExecuteError: ERROR 000732: Input Table: Dataset in_memory\points does not exist or is not supported

Brian

0 Kudos
JeremyMullins4
New Contributor III

Just as an amendment to Darren's awesome script, I noticed that my output was including intersections at endpoints of all line segments, and not just between streets. For example, in my feature class, Main St was made up of ten different line segments (for E911 purposes).

To counter act this, I simply added in the following Dissolve tool before finding the intersection (changes in bold😞

out_fc = r'C:\Users\jmullins\Desktop\GEO\GEOImportTool.gdb\Scratch\points'

int_pt = r'C:\Users\jmullins\Desktop\GEO\GEOImportTool.gdb\Scratch\int_pt'

diss_fc = r'C:\Users\jmullins\Desktop\GEO\GEOImportTool.gdb\Scratch\diss_fc'

arcpy.Dissolve_management(fc,diss_fc,["YourStreetNameField"],"","SINGLE_PART")

arcpy.Intersect_analysis(diss_fc,int_pt,output_type='POINT')

This will dissolve all streets by their street name, which should decrease the number of redundant or unnecessary points in your output. Many may not use Darren's script for this in particular, especially if they aren't interested in street intersections, but I just wanted to add it in there for those who may need it.

Thanks again, everyone.

0 Kudos
JeremyMullins4
New Contributor III

Darren,

I'm getting the following issue running your python script:

Traceback (most recent call last):

  File "C:\Users\jmullins\Desktop\Test.py", line 3, in <module>

    sr = arcpy.Describe(fc).spatialReference

NameError: name 'arcpy' is not defined

I threw an import arcpy underneath import os, and now I am getting this error:

Traceback (most recent call last):

  File "C:\Users\jmullins\Desktop\Test.py", line 8, in <module>

    arcpy.Intersect_analysis(fc,int_pt,output_type='POINT')

  File "C:\Program Files (x86)\ArcGIS\Desktop10.4\ArcPy\arcpy\analysis.py", line 289, in Intersect

    raise e

RuntimeError: Object: Error in executing tool

I apologize for being inept at python scripting, and I appreciate any help you (or anyone else) can provide. Thanks!

0 Kudos