4

I have a polygon layer made up of grid cells, illustrating a survey system: enter image description here

I'm trying to create a point on each corner of the polygon. I've used a geoprocessing tool called "Feature Vertices to Points" in ArcGIS, but what it does is create a point for each vertice:

enter image description here

Is there a tool out there that will allow for the creation of corner points?

Please note this is a small subsection of the survey grid that I clipped out to run a proof of concept.

What I'm basically trying to do is create these points of this grid (which was created many years ago) and then apply the same methodology to the latest version of the survey grid, which is based off of NAD83, to see how much and where the grids have shifted.

The differences in the grids are important when determining how measurements change when it comes to locating buildings, wells etc.

  • Why do you have so many vertices for rectangles? If you were to remove all the non essential vertices (ie: the ones between corners) you would be able to get what you want. Having all those vertices is not a good thing to have in your polygons. – Ryan Garnett Feb 2 '15 at 21:56
  • I agree, thanks Ryan. I did not create the original polygons, they come off our main server. Is there a tool I could use to clean up all non essential ones? – Jennifer Feb 2 '15 at 21:57
  • What GIS application are you using? In QGIS you could look at using Vector - Simplify Geometries. ArcGIS will have a similar tool. It will remove vertices from a shapefile from within a tolerance, which is based on a distance. – Ryan Garnett Feb 2 '15 at 22:07
  • I'm using ArcGIS 10.1 – Jennifer Feb 2 '15 at 22:13
  • 2
    I would caution against removing those vertices unless you know you can. They may be there for a reason - for example, the bottom left cell's west line doesn't appear to be straight. Is the grid topologically correct (meaning all cells share common vertices, with no overlap or gap)? One method you might try is Feature to Line first, and then Feature to Vertices on those with a point location restriction to ends. Not sure if going to lines will work though - the overlap may create a line from each segment rather than each side. Whichever way you'd need to clean duplicates from the result. – Chris W Feb 2 '15 at 22:32
1

Solution One: Polys to Lines then Points

Based on a test I just ran, I suggest a process of first running Feature to Lines on your grid, and then running Feature Vertices to Points on the generated lines with a point type of BOTH_ENDS. Follow that up with a delete duplicate because there will be 8 points at every interior intersection and 4 on the exterior. The solution isn't perfect however.

enter image description here

First, it makes the assumption that your grid is topologically correct - adjoining cells in the grid have exactly the same vertices in the same places. If not, this may fail. I ran a test with a grid created by fishnet (hence no extra vertices), as well as by drawing a three cell, topologically correct 'grid' shown in the image. In both cases Feature to Lines created line segments that ran from one cell corner to the other - they were not broken up by intermediate vertices if present. If the cells aren't topologically correct, cell sides may generate multiple line segments and you end up with extra points/vertices.

Second is the big catch - it will only work on the interior lines. The north and west sides of the top left cell will be considered a single line. So in the next step, Feature Vertices to Points with end points, the corners of the overall grid won't get points (as those corners aren't ends.) In the image, the bright green dots are the result of FVtP. Note that there are only three lines around the outside of this 'grid' - the top half, and the bottom two quarters. Hence there are no points at the outside corners, because they are not the starts or ends of lines.


Alternative solution: Spatial Join.

Go ahead and run your Feature Vertices to Points on your original grid. As you noted, it creates a bunch of extra points that aren't at the corners. Take those points and Spatial Join them to themselves with a one-to-one relationship and using intersect as the method (possibly with a small search radius). Not only do you have points where you don't want them, but you have multiple points on top of each other because your cells have overlapping edges. But this works to your advantage here.

Once joined, open up the attribute table and you'll see a join count column. Any point that doesn't have four or greater in that column is not a corner point (because it would have come from a vertex shared by only two polygons, so there's be only two points to join). Only points with a count of four or eight (as noted in the first paragraph of the answer) are the points you're looking for. Once you delete all the others with lower join counts, you can run delete duplicate on the remaining points to get down to one point per corner.

0

I actually made a tool that does this, you can download the toolbox here:

Create Grid Corner Points

I'm actually not completely finished with it yet because it doesn't remove any duplication. I plan on adding that as an option.

But, give the tool a try, and let me know if it's what you're looking for. If it is, I'll add the code to remove any duplicate points.

Here's a screenshot of the parameters: enter image description here

  • Thanks for your insight and time on this...I'll give it a try today and let you know – Jennifer Feb 3 '15 at 14:17
  • I could send you a screen shot of the entire grid I'm working with...and the subsection I'll try the steps you suggested – Jennifer Feb 3 '15 at 15:45
  • @JennD did you have a chance to try the tool yet? – ianbroad Feb 3 '15 at 15:46
  • working on it now.... – Jennifer Feb 3 '15 at 15:49
  • 1
    @ChrisW yeah, I still have it. I just need to track it down. I didn't realize this was linked to my Dropbox account. I'll fix the link by sometime tomorrow. – ianbroad Jun 10 '15 at 0:21
0

I think there are (at least) two ways to think about this: intersections and corners.

If you want to extract corners within some threshold (for example, below, between 45 and 135 degrees), you can do so by inspecting the arcpy geometry objects:

>>> import math
... polyFC = "parcels" # polygon layer
... sr = arcpy.Describe(polyFC).spatialReference # spatial ref
... lines = [] # lines list
... points = [] # points list
... with arcpy.da.SearchCursor(polyFC,"SHAPE@",spatial_reference=sr) as cursor:
...     for row in cursor: # loop polygons
...         for part in row[0]: # loop polygon parts
...             line = arcpy.Polyline(part,sr) # convert to line
...             pt_count = 1
...             second_point = arcpy.PointGeometry(part[1],sr) # save 2nd point for later
...             for pnt in part: # loop line vertices
...                 pnt = arcpy.PointGeometry(pnt,sr) # current vertex   
...                 if pt_count > 1:     
...                     if pt_count >2: # can only get angle on 3rd+ vertex    
...                         distAB = oneBack.distanceTo(twoBack) # dist 1 vertex back to 2 vertices back   
...                         distBC = pnt.distanceTo(oneBack) # dist current point to 1 vertex back    
...                         distAC = pnt.distanceTo(twoBack) # dist current point to 2 vertices back
...                         angB = math.degrees(math.acos((((distAB*distAB)+(distBC*distBC))-(distAC*distAC))/(2*distAB*distBC))) # angle at 1 vertex back
...                         if angB > 45 and angB < 135: # if angle between your threshold values
...                             points.append(oneBack) # add to points list  
...                     twoBack = oneBack # advance vertex    
...                 oneBack = pnt # advance vertex
...                 pt_count += 1 # advance vertex counter
...             pnt = second_point # need to loop back around to beginning for first point
...             distAB = oneBack.distanceTo(twoBack)    
...             distBC = pnt.distanceTo(oneBack)    
...             distAC = pnt.distanceTo(twoBack)   
...             angB = math.degrees(math.acos((((distAB*distAB)+(distBC*distBC))-(distAC*distAC))/(2*distAB*distBC)))  
...             if angB > 45 and angB < 135:
...                 points.append(oneBack)
...             lines.append(line) # optional line output
... arcpy.CopyFeatures_management(lines,r'in_memory\lines') # write lines
... arcpy.CopyFeatures_management(points,r'in_memory\points') # write points

enter image description here

As with other solutions, this will create duplicate points.

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.