def getCardinal(angle): lstCardinal = [[22.5,"E"], [67.5, "NE"], [112.5, "N"], [157.5, "NW"], [202.5, "W"], [247.5, "SW"], [292.5, "S"], [337.5, "SE"], [360, "E"]]
def getCardinal(angle): lstCardinal = [[11.25,"E"], [33.75,"ENE"], [56.25, "NE"], [78.75, "NNE"], [101.25, "N"], [123.75, "NNW"], etc... [348.75, "ESE"], [360, "E"]]
Hi Mark,I had some problems with the "custom" coordinate system, but I have attached a toolbox with the functionality and also an updated file geodatabase. Unzip the toolbox ("toolshare2.zip") and navigate with the ArcCatalog window to the unzip location. Try the tools inside. Hope they work for you.The SL distance (length) that is returned follows the linear unit of the input featureclass. In your case it is US_Foot.Kind regards,Xander
Hi Mark,When I was asking for a few streams, I was refering to a featureclass. Maybe you can attach a few streams as featureclass in a zipped fgdb or as a zipped shapefile (although some fieldnames will be renamed when exporting to shapefile). This way I can look at the geometry itself and the spatial reference and test my script.Kind regards,Xander
Hi Mark,If your data is located somewhere at the border of Pennsylvania and West Virginia, the coordinates are in decimal degrees (not miles). The coordinates seem to correspond to a stream, just next to the Golden Oaks rd (PA 18).Using decimal degrees to calculate the angle and the straight distance in the scrips will not give correct answers. The coordinates should be projected first. I don't know what the reason is for the calculation to trow a 99999 error. If you are willing to share a small part of your data (streams) I can have a look.Kind regards,Xander
Hi Mark,This sounds a lot like it has to do with the coordinate systems. Can you specify the following:- coordinate system of your streams dataset- coordinate system of your data frameIf both are geographic, can you provide me a projected coordinate that suits your data (for the length calculation)? Probably the straight line geometry has to be created with the spatial reference of the source, and if that is geographic, it needs to be projected to obtain the proper length. This can all be done in the field calculator script.Just to be sure can you also provide an example:- start coordinate- end coordinate- distance measured manually (the correct distance)- distance calculated by the scriptKind regards,Xander
Hi Mark,I see Duncan has already provided you with a good way to calculate the intra-nodal distance. I was wondering however, since your goal is to "determine the average stream flow direction within a polygon layer" and you don't want to use your DEM (aspect) for this purpose, you could do something else. What if you would create fields for each cardinal flow direction and each field would be filled with the sum of the lengths of coordinate pairs within each stream in that cardinal flow direction. My guess is that this would provide a better understanding of the flow direction once you summarize it within a polygon.Kind regards,Xander
Mark,You can compute the straight line distance of any polyline with the following python field calculate. First create a field of type double then run a calculate with the python expression getSLDist(!shape!) and the pre-logic script code is:import arcpy def getSLDist(geom): # Get the end points of the polyline fp = geom.firstPoint tp = geom.lastPoint # Create an Array object and add points to it array = arcpy.Array() array.add(fp) array.add(tp) # Create a polyline from array, as it only has 2 points in it # it must be a straight line, then return its length line = arcpy.Polyline(array) dist = line.length return dist Duncan
import arcpy def getSLDist(geom): # Get the end points of the polyline fp = geom.firstPoint tp = geom.lastPoint # Create an Array object and add points to it array = arcpy.Array() array.add(fp) array.add(tp) # Create a polyline from array, as it only has 2 points in it # it must be a straight line, then return its length line = arcpy.Polyline(array) dist = line.length return dist
Hi Mark,Although this type of analysis is normally done using the raster format, it can be done using a featureclass (shapefile). Assuming that you are interested in an angle between the start point and the end point of each feature you could do this:open the attribute table of your shapefileadd a new field that will hold the cardinal flow direction, make sure it is a text field (let's call this field "CardFD")right click on your new field "CardFD" and select "Field Calculator..." to open the Field CalculatorChoose Python as parserSwitch the "Show Codeblock" onPaste the code below in the "Pre-Logic Script Code":import arcpy from math import atan2, pi def getCardinal(angle): lstCardinal = [[22.5,"E"], [67.5, "NE"], [112.5, "N"], [157.5, "NW"], [202.5, "W"], [247.5, "SW"], [292.5, "S"], [337.5, "SE"], [360, "E"]] for item in lstCardinal: value = item[0] if angle < value: cardinal = item[1] break return cardinal def calcGeomCardinality(polyline): pnt1 = polyline.firstPoint pnt2 = polyline.lastPoint angle_deg = (atan2(pnt2.Y - pnt1.Y, pnt2.X - pnt1.X)) * 180.0 / pi if angle_deg < 0: angle_deg = 360 + angle_deg return getCardinal(angle_deg)Paste the line below in as formula (just below "CardFD =")calcGeomCardinality( !SHAPE!)Click "OK"This will take each polyline feature and extract the from and to node from it. Next it will calculate the angle and parse it to cardinal flow direction.You can also write the angle itself to a new field:add a new field (double or float) that can hold the angle between the start and end point . Let's call this field "FlowAngle"right click on your new field "FlowAngle" and select "Field Calculator..." to open the Field Calculatorit will probably show the code from cardinal flow direction. Replace the code in the "Pre-Logic Script Code" byimport arcpy from math import atan2, pi def getAngle(polyline): pnt1 = polyline.firstPoint pnt2 = polyline.lastPoint angle_deg = (atan2(pnt2.Y - pnt1.Y, pnt2.X - pnt1.X)) * 180.0 / pi if angle_deg < 0: angle_deg = 360 + angle_deg return angle_degPaste the line below in as formula (just below "FlowAngle=")getAngle( !SHAPE!)Click "OK"If you are going to perform some analysis to determine the predominant angle, please be aware that the resulting angle does not have to be representative for the area.Kind regards,Xander
import arcpy from math import atan2, pi def getCardinal(angle): lstCardinal = [[22.5,"E"], [67.5, "NE"], [112.5, "N"], [157.5, "NW"], [202.5, "W"], [247.5, "SW"], [292.5, "S"], [337.5, "SE"], [360, "E"]] for item in lstCardinal: value = item[0] if angle < value: cardinal = item[1] break return cardinal def calcGeomCardinality(polyline): pnt1 = polyline.firstPoint pnt2 = polyline.lastPoint angle_deg = (atan2(pnt2.Y - pnt1.Y, pnt2.X - pnt1.X)) * 180.0 / pi if angle_deg < 0: angle_deg = 360 + angle_deg return getCardinal(angle_deg)
calcGeomCardinality( !SHAPE!)
import arcpy from math import atan2, pi def getAngle(polyline): pnt1 = polyline.firstPoint pnt2 = polyline.lastPoint angle_deg = (atan2(pnt2.Y - pnt1.Y, pnt2.X - pnt1.X)) * 180.0 / pi if angle_deg < 0: angle_deg = 360 + angle_deg return angle_deg
getAngle( !SHAPE!)
Signed in members can post, follow updates, and more. New here? Register a free account.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.