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.
RhettZufelt_0-1647367006737.png
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).
RhettZufelt_1-1647367058676.png
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_