I'm trying to create polygon features depicting the crowns of trees based on a CSV of tree measurements that were collected in the field.
Each tree record includes the co-ordinates of the trunk in X and Y fields, and the crown dimensions are stored as 4 measurements (in metres) that record the distance from the trunk to the edge of the crown at each cardinal direction (north, south, east and west). I need to show crowns that accord with these measurements (i.e. a tree with a 'Crown East' field of 4m and a 'Crown West' field of 2m will need to produce a crown polygon that is suitably asymmetrical).
Is there any way to use Geoprocessing tools to draw ellipses / polygons to represent the crowns based on this information?
I'm using ArcGIS Pro 2.7 with a Basic licence.
My first thought was the Extrude Features to 3D Symbology feature: https://pro.arcgis.com/en/pro-app/latest/help/mapping/layer-properties/extrude-features-to-3d-symbol...
But this would just make your trees the right height. I'll keep thinking about your actual question.
This tool would create ellipses using your attributes, but it assumes a major and a minor axis. (symmetrical, not asymmetrical); https://pro.arcgis.com/en/pro-app/latest/help/data/distance-direction/create-ellipses.htm
And my last idea is to use Arcade Expressions, but I don't have a specific suggestion to help.
Thanks for this. I did have a look at the Create Ellipses tool, but as you say, it seems to only produce symmetrical ellipses. I'll investigate Arcade Expressions and see if I can work anything out.
Not sure about a geoprocessing tool, but with arcpy this is pretty simple.
Though, with 4 measures from the point, it will create rectangles oriented N/S/E/W.
Basically, would add new columns for 4 coordinate pairs (X1,Y1, X2, Y2,........Y4).
then you would add/subtract the measures from the coordinates giving you the corner points of the polygon.
Dump those points to a polygon, and you have your rectangles.
Could even subtract a certain amount from the difference, then buffer with that amount to make them rounded corner rectangles (same point as above, but minus 10 from polygon, then 10 on buffer).
If arcpy is an option for you, I can share the code that did the above. would just need some tweaking to fit your dataset.
R_
With GeoTools, you could massage the spreadsheet then use one of these methods to generate the polygons.
Thanks for this!
If you're happy to share the code, I'll have a look and see if I can get to the buffered rectangles as above. Unfortunately, I'll probably have to keep going from there to see if I can get them a little closer to real crown shapes / ellipses after that, but this is definitely a step in the right direction.
This is the code I used to do the above.
import arcpy
# Overwrite pre-existing files
arcpy.env.overwriteOutput = True
##### set input point feature class and output FC for polygons and buffers
infc = r'Database Connections\pathToInputFeatureClass\testpoints'
outfc = r'Database Connections\pathToOutputPolygonFeatureClass\polygons'
bufffc = r'Database Connections\pathToOutputBufferPolygonFeatureClass\buffers'
## set the size of the buffer (in map units) for the buffered polygons
buff = 10
## this line caluclates the x,y values of the points in fields named "x" and "y".
## can omit if you already have these columns with x,y coordinates of the point
arcpy.management.CalculateGeometryAttributes(infc, "x POINT_X;y POINT_Y", '', '', None, "SAME_AS_INPUT")
### Expects these fields in the input FC. "x" and "y" are the coordinates
### the rest I added manually to the FC to hold the new corner coordsinates
### and the distance measured in each cardinal direction from the tree
# Index numbers to make it easier to tell what row[#] refers to.
# [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]
fields = ['X1', 'Y1', 'X2', 'Y2', 'X3','Y3', 'X4', 'Y4','x', 'y', 'n', 's', 'e', 'w']
### This updatecursor adds/updates the new corner coordinate columns
### the "- buff" subtracts the buffer value from each new coordinate
### set to buff=0 above to have straight output without buffer
with arcpy.da.UpdateCursor(infc, fields) as ucursor:
for row in ucursor:
row[0] = row[8] - row[13] - buff
row[1] = row[9] + row[10] - buff
row[2] = row[8] + row[12] - buff
row[3] = row[9] + row[10] - buff
row[4] = row[8] + row[12] - buff
row[5] = row[9] - row[11] - buff
row[6] = row[8] - row[13] - buff
row[7] = row[9] - row[11] - buff
ucursor.updateRow(row)
## Fields to establish the search curson on the newly populated input FC.
fields = ['X1', 'Y1', 'X2', 'Y2', 'X3','Y3', 'X4', 'Y4', 'Id','SHAPE@']
## fields for the insert cursor to insert polygons and Id into output FC
## "SHAPE@" is the geometry column that we insert the polygon into
## "Id" is the Id column of the input point
## this way, there is an Id from the respective point in the Polygon
## you may need to update/add to this if you want other fields copied over
ifields = ['SHAPE@','Id']
## Search cursor inside insert cursor
## Search cursor extracts the new coordinate pairs
## insert cursor inserts the geometry and name ('Id') into the polygon FC
with arcpy.da.InsertCursor(outfc, ifields) as icursor:
with arcpy.da.SearchCursor(infc,fields) as cursor:
for s in cursor:
coords = [(s[0],s[1]),
(s[2],s[3]),
(s[4],s[5]),
(s[6],s[7]),
(s[0],s[1])]
name = s[8]
icursor.insertRow((coords,name))
### If you set a buffer distance, this will create the buffer to round the corners
if buff > 0:
arcpy.analysis.Buffer(outfc, bufffc, buff, "FULL", "ROUND", "NONE", None, "PLANAR")
R_