How to add points in order along a stream reach in ArcGIS? - arcgis

I have a stream network in ArcGIS - i.e. a series of polylines, and along each stream part I have added points. For each of the points I have extracted the height and flow from underlying rasters and I have also extracted data from the intersecting polylines including minimum, mean and max height of the polyline, the HydroID and the nextdownID. The points also have their own ID but I have noticed these are not in order.
What I would like is to add stepID to each of the points, where at the beginning of each river reach (each polyline) the first point is step 1 and this increments upwards until the end of the reach. So if there were 10 points along a polyline, the first point would have a stepID value of 1 and the last point would have a stepID value of 10.
This sounds quite easy but not sure how to do it. Any help would be great.

You can construct points along the line at specific intervals using the construct points tool/function.
Click the Edit tool Edit Tool on the Editor toolbar.
Click the line feature along which you want to generate points.
Click the Editor menu and click Construct Points.
http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//001t00000029000000.htm
To automate the numbering, you might look into flipping the lines so all the tails point in one direction - up or downstream. Double click on a line, then right click to see the "flip" command. If you use the points set up from the method above, it might order from tail to head.
Another option is to create your own field for the stepID. Create a attribute join to the stream segment, and give each joined record a unique number. Go through your records selecting each group of ten, then sort by FID (check these are in order) then calculate value for stepID = FID - x
where x = the lowest FID in the stream segment's stepID. This thought might help you figure out how to coax the numbers out correctly.

I had this problem before and solved it this way. It is NOT a pretty solution. Would love to hear if there is a more elegant way of doing this
.
For clarity I'll call the pointdataset you mention the 'inputpoints'.
Step 1: getting the points in the right order
If your inputpoints are sometimes far away from the lines, first project them to your lines.
Give your lines a unique line number and join it to the closest inputpoint features
Generate points along lines: use your polylines and genarate a lot of points on them. I'll call this dataset the helperpoints. Fill in a distance that is smaller then the smallest distance between two of your inputpoints.
Make sure your polylines have the right 'direction'. You can check it by using a symbology with arrows, and if needed correct it with the flip editing tool.
Add an IDfield to your helperpoints, type float or double, and create sequential idnumbers in it (https://support.esri.com/en/technical-article/000011137).
Spatial join: the inputpoints are your target, the helperpoints the join features. Keep all the target features. You only need to join the IDfield from the helperpoints. Right click the IDfield in the field map, and make the merge rule 'Mean'. Set the Match option to 'within a distance', and make the search radius 1.5 x the distance that you used in the generate points along line step.
Use the sort tool and sort your spatial join output on the IDfield you just added, then on the lineID you you added on step one. If you have the advanced licence you can do it at once.
Step 2: Generating the StepID
Add a new field to your sort output, and call it StepID
Use the field calculator to fill it. I used this code to make the numbering restart every time there is a new line.
rec=0
oldid = -1
def autoIncrement(lineid):
global rec
global oldid
pStart = 1
pInterval = 1
if rec == 0 or lineid!= oldid :
rec = pStart
else:
rec += pInterval
oldid = lineid
return int(rec)
Expression: autoIncrement( !lineID! )
Expression type: Python
It might still mess up if you have lines very close to each other, or have weird curls on the end. But for the rest this should work!

Related

Index for trivial pursuit game's spaces

I'm trying to code a trivial pursuit game. I want to give an id for every space of the board in order to use them for the movements. I need to know for every space which is next to which/match with each other.
But because of the geometry of the board(extern circle + radii), I didn't find the right logic behind this.
I am thinking of an ID based on 7 numbers (for the 6 radii + the circle). For example :
//this is not my code, i'm just trying to show example of IDs
center = [0][0][0][0][0][0][-2]
one on the "2nd radius" = [0][3][0][0][0][0][-2]
one the circle and the "3rd radius" = [0][0][6][0][0][0][22]
one on the circle = [0][0][0][0][0][0][21]
I have no idea if it's gonna work or if it's optimal, i will try and see.
If some of you have any better idea for name the ID, i would be happy to listen to them.
Here is an image of the board.
enter image description here
Thank you for helping!
OK, seeems you are inventing some coordinate system for this wheel for easy addressing and easy transtions between cells. System with many indices looks too complex.
Perhaps two-index scheme would be appropriate. Resembles polar coordinates:
The first index 0..6 as distance from the center.
The second one 1..42 - angular position.
So center cell is A[0][0] (the second index is not defined, we can choose any)
It's neighbors are A[1][1], A[1][8], A[1][15] ..A[1][36] (marked with 1 at your picture)
Similar for the next cells at the rays A[2][1], A[2][8], A[2][15] ..A[2][36] and so on
Wheel cells are A[6][1], A[6][2]..A[6][42]
Now neighbor cells have coordinates where one index differs by 1 (except for central cell, extra case)
Is this scheme suitable?

How to iterate over a pandas data frame when using the basemap function to check the result

I am trying to write apython script that will do a geometric transformation for the long/lat values, namely the rotation. However, I want to resulted long/lat to preserve the location, for example if the otiginal coordinate is in the land I want the rotated one to be also in land. Therefore, I have used basemap
I wrote the following script and it works fine, till I tried to add a while loop. My objective from adding the while loop is to compare the original value with the rotated one and if they dont match, the rotation angle will change till they match. I will show my concept without adding the while loop first:
def rotation(dfc):
# Rotation
choose a rotation angle that will match the location of the rotated
coordinates, and set the result to 1 if they match
while row['result']=0
choose another rotation angle
do the rotation again
check the result of the rotated points
if still they dont match stay in the loop and choose another alpha
if not break and go to the next row
I know it needs simple steps, but I am not able to figure out how to add the loop for row wise functions in dataframes
Actually this problem can be solved without using df.iterrows.
I just initiated a variable to be equal 0 and then added a while loop. So my pseudocode looks like :
counter=0
while counter != len(df['col1'])
choose new random variable
do the calculation using dfc.apply()
re-calculate counter

How to Structure Lists

I am working on a vb.net auto-focus routine and have the image processing part worked out, basically I do some edge detection, convert to gray-scale and then measure the standard deviation to work out the most 'in focus' point of the image.
I have done this with a number of images, and it almost comes out as a normal distribution, now I want to start to integrate this with my microscope and a stepper motor.
The concept is that I would move through a lower and upper limit on the stepper motor, and measure the above through live-view, recording the values in a list. In my case the two things I want to record are the position, and the double standard deviation value.
I am wondering what the best way to record these are, should it be
recorded as a typed list, or a dictionary or another method?
Once I record all of these values, I would want to go through the values to conduct some simple analysis of them, so if that was the case
how would I then be able to determine the average, min, max etc?
My first attempt of storing the information was in a typed list, where I had essentially done the below;
Public ZPositions As New List(Of Zfocus)
Public Class Zfocus
Public Position As Integer
Public GreyStDev As Double
End Class
The second way was to use a dictionary;
Public ZPosition As New Dictionary(Of Integer, Double)
However in both cases, I am not sure how I can either pull out a single maximum position value (e.g. Position integer,) or from the dictionary the position value (integer) which (sort of) corrosponds to the best auto-focus position.
The Third added bonus, is to be able to pull out any postions above a
specific value, which may corrospond to having some focus information
within them for focus stacking?
Many thanks
Big thanks to jmcilhinney, this solved my issue and works a treat!
Went with a strongly typed list (the ZFocus list) and then I could do the below;
MaxPosition = ZPositions.First(Function(zp1) zp1.GreyStDev = ZPositions.Max(Function(zp2) zp2.GreyStDev))
This allowed be to set up an auto-focus routine which loops through a number of images (as a test), stores the position (e.g. image number in this case) and the intensity edge information, and at the end then pull out the strongest intensity information which forms the best auto-focus point in my case

Building an MKPolygon using outer boundary of a set of coordinates - How do I split coordinates that fall on either side of a line?

I'm trying to build a MKPolygon using the outer boundary of a set of coordinates.
From what I can tell, there is no delivered functionality to achieve this in Xcode (the MKPolygon methods would use all points to build the polygon, including interior points).
After some research I've found that a convex-hull solves this problem.
After looking into various algorithms, the one I can best wrap my head around to implement is QuickHull.
This takes the outer lat coords and draws a line between the two. From there, you split your points based on that line into two subsets and process distance between the outer lats to start building triangles and eliminating points within until you are left with the outer boundary.
I can find the outer points just by looking at min/max lat and can draw a line between the two (MKPolyline) - but how would I determine whether a point falls on one side or the other of this MKPolyline?
A follow up question is whether there is a hit test to determine whether points fall within an MKPolygon.
Thanks!
I ended up using a variation of the gift wrap algorithm. Certainly not a trivial task.
Having trouble with formatting of the full code so I'll have to just put my steps (probably better because I have some clean up to do!)
I started with an array of MKPointAnnotations
1) I got the lowest point that is furthest left. To do this, I looped through all of the points and compared lat/lng to get lowest point. This point will definitely be in the convex hull, so add it to a NSMutableArray that will store our convex hull points (cvp)
2) Get all points to the left of the lowest point and loop through them, calculating the angle of the cvp to the remaining points on the left. Whichever has the greatest angle, will be the point you need to add to the array.
atan(cos(lat1)sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1), sin(lon2-lon1)*cos(lat2))
For each point found, create a triangle (by using lat from new point and long from previous point) and create a polygon. I used this code to do a hit test on my polygon:
BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO);
If anything was found in the hit test, remove it from the comparison array (all those on the left of the original array minus the hull points)
Once you have at least 3 points in your cvp array, build another polygon with all of the cvp's in the array and remove anything within using the hit test.
3) Once you've worked through all of the left points, create a new comparison array of the remaining points that haven't been eliminated or added to the hull
4) Use the same calculations and polygon tests to remove points and add the cvp's found
At the end, you're left with a list of points in that make up your convex hull.

Line intersections

Im writing an application that will calculate the focal length of a camera based on the lines that can be seen in the photograph. For instance, if you take a picture of a room, the ceiling line can be one straight line (horizontal), the floor can be another straight line (horizontal) and the wall can be the third straight line (vertical). The aim of my application is for the user to select these straight lines one at a time, and once 3 lines are selected, the lines will need to be intersected to form a "triangle".
My problem is that because the lines selected don't necessarily intersect, how do I extend a line until it intersects with another line? In my application I have the start and end positions of all 3 user selected lines (Vector2's). But how do I extend each line until it intersect with the other 2 lines?
If anyone needs an image to clarify what I mean, send me a reply and Ill upload one to Flickr
Say each line is represented by two vector2's: v1 and v2, all the points in that given line will be given by the equation: p(x) = v1 + x(v2-v1). Each line will have its equation in this form. For each pair of lines, you will have to find the value of x that gives you the same p(x) for both equations; p(x) will be the point of intersection of those two lines.
Sounds like you need to do 3 things.
Extend the lines to the end of the picture (in your code, not visible to the user).
Calculate line intersection. See this answer: detecting line intersection
on the user's end, extend the lines until the intersection point if there is one on the picture.