Friday 14 June 2019

qgis - Determine start/end points for line slope calculation



This is a follow up question based off of this question.



I have a line feature class representing storm drains and a point feature class representing where storm drains are connected. The point feature class has an elevation for each point allowing me to determine the slope of the storm drain as the difference in elevation from start to end divided by the length of the storm drain. However, most of my points act as starting points for one storm drain and end points for another at the same time. I do know that the start point should always be the point with a higher elevation to facilitate water flow.


How can I calculate the slope for each line segment and designate which points are the start/end points for each line?


Would it be better to calculate new lines based off of my points layer that would include a slope field or is there a way to automate this calculation between the two layers?


I have an ArcMap Advanced license but no 3D or Spatial analyst extensions. I am open to Python and QGIS solutions. I just don;t want to have to enter these values in manually as I know there must be a way to automate it.


enter image description here



Answer



To simply state your problem, you have one set of points with a value but those points/values apply to both ends of a line; you want to add two different point values as separate attributes to one line. There are (at least) two ways to do this.




The first is to extract the start and end nodes of all your lines as points. Since you have an Advanced license, this is easy to do with Feature Vertices to Points. You'd have to extract the start and end nodes to separate point files, since there's no attribute created to distinguish them and you'd have stacked points. This process is what allows you to assign the same point value to two different lines as different attributes - the two files will largely have the same points, but each set defines if that point is the start or end of the line.


Once you've done that you can use a Spatial Join between your points with values and the new start/end points to transfer the values (two joins). Then you can regular joins or Join Field (again, twice) based on line ID (which is an attribute of their extracted points) to transfer the start/end values to two new fields in the line data. This is the method outlined at How to assign node IDs to links in a network?





The second method, Felix's solution from Assign point IDs to respective start and end attributes of a polyline, potentially has a lot more field calculation and manipulation, but fewer joins and doesn't have the Advanced license requirement to extract the nodes. Instead it relies on making a unique ID field for the points based on coordinates, and matching that to new fields in the line file that identify the coordinates of the start and end points.


To start with, you need an identifier for the value points. Add two new fields to that point file, X and Y (floats to hold decimals if needed). Add a third called XY but make it a string. Using Calculate Geometry in the attribute table (right-click field heading) you can add the x and y coordinate values to those two new fields, then use a field calculation on the third to combine (concatenate) the values into a single string - something like 734.54,234.87. In theory that should uniquely identify each point.


Now you'll do the same in your line file, except you have to do all those steps twice - once (three fields) for the start points, and once (three more fields) for the end points. There is a special syntax you can use to access the geometry of the line in the field calculator. From Michael's comment on Felix's answer at the other question, an example would be:


str(round(!Shape!.firstPoint.X,3)) + "," + str(round(!Shape!.firstPoint.Y,3))

The syntax I'm referring to is the !shape!.firstPoint.X part. It's discussed in the help files for the Calculate Field tool. You'll also note that Michael's formula is set up to do it all in one calculation, so you'd really only need two fields instead of six because it combines steps. The same could apply to the points if you don't use the Calculate Geometry tool. The rest of the syntax is converting numeric to strings and rounding. Note Felix's comments on your question about truncating and rounding and source xy tolerance. The issue being raised is making sure that the generated ID string actually matches when you do it for both the points and lines since it's based on math to coordinate values.


What you should end up with are three string attribute fields that have matching values across the two feature classes - ID in the points, and a startID and endID in the lines. You'll add two more fields to lines - startelev and endelev At this point you can do two regular joins (or use the Join Field tool as mentioned above) based on the ID fields. One will transfer your point values to the start fields, and the other will do the end fields.


With that complete you can add your new slope field and run the calculation based on the startelev and endelev fields.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...