Select to view content in your preferred language

winddirection

612
1
04-04-2022 03:11 AM
Labels (1)
AnitaBuschgens
New Contributor

Does anyone have a suggestion how to create a buffer around a polygon based on windspeed and winddirection? The normal geoprocessing tool 'buffer' is mainly based on distances and thereby creating circles. A want to use these bufferpolygons as riskzones for example atmospheric deposition or as a riskzone during a major fire. I am using arcgis desktop 10.8.1

0 Kudos
1 Reply
JohannesLindner
MVP Frequent Contributor

Hmmm... My first instinct would be to create an elliptical buffer, with the feature being in the ellipsis focal point that is pointed into the wind.

 

def elliptic_buffer(in_features, id_field, major, minor, azimuth, out_features):
    """Creates an alliptic buffer around the input features.

    in_features: input feature class / layer
    id_field: name of a unique id field in the in_features
    major: buffer distance in the major elliptical axis (meters)
    minor: buffer distance in the minor elliptical axis (meters)
    azimuth: geographic angle of the buffer (degrees, North = 0°, East = 90°)
    out_features: output feature class
    
    """
    arcpy.env.addOutputsToMap = False
    # read shapes and id
    shapes = [row for row in arcpy.da.SearchCursor(in_features, ["SHAPE@", id_field])]
    sr = shapes[0][0].spatialReference
    # create ellipsis parameters
    ellipsis_table = arcpy.management.CreateTable("memory", "ellipsis_table")
    fields = ["X", "Y", "MAJOR", "MINOR", "AZIMUTH", "ID"]
    for f in fields:
        arcpy.management.AddField(ellipsis_table, f, "DOUBLE")
    with arcpy.da.InsertCursor(ellipsis_table, fields) as cursor:
        for shape, id in shapes:
            densified_shape = shape.densify("DISTANCE", 10, 10)
            for part in densified_shape:
                for point in part:
                    cursor.insertRow([point.X, point.Y, major, minor, azimuth, id])
    # create ellipsis for each point of each densified feature (polyline)
    ellipsis_fc = arcpy.management.TableToEllipse(ellipsis_table, "memory/ellipsis_fc", "X", "Y", "MAJOR", "MINOR", "METERS", "AZIMUTH", "DEGREES", "ID", sr)
    # translate features, so that each determining point is in the focal point pointed into the wind
    dist = (major**2 - minor**2)**(0.5)
    dx = dist * math.sin(azimuth * math.pi / 180) / 2
    dy = dist * math.cos(azimuth * math.pi / 180) / 2
    with arcpy.da.UpdateCursor(ellipsis_fc, ["SHAPE@XY"]) as cursor:
        for row in cursor:
            cursor.updateRow([[row[0][0] - dx, row[0][1] - dy]])
    # create output fc
    arcpy.env.addOutputsToMap = True  # add out_features to map
    out_fc = arcpy.management.CreateFeatureclass(os.path.dirname(out_features), os.path.basename(out_features), "POLYGON", spatial_reference=sr)
    id_type = [f.type for f in arcpy.ListFields(in_features) if f.name == id_field][0]
    if id_type == "OID":
        id_field = "FID"
        id_type = "LONG"
    arcpy.management.AddField(out_fc, id_field, id_type)
    # convert ellipses to polygon (FeatureToPolygon doesn't keep the id_field...)
    ellipses = [row for row in arcpy.da.SearchCursor(ellipsis_fc, ["ID", "SHAPE@"])]
    ids = {e[0] for e in ellipses}
    with arcpy.da.InsertCursor(out_fc, ["SHAPE@", id_field]) as i_cursor:
        for id in ids:
            polylines = [e[1] for e in ellipses if e[0] == id]
            polygon = polylines[0].convexHull()
            for polyline in polylines:
                polygon = polygon.union(polyline.convexHull())
            i_cursor.insertRow([polygon, id])



elliptic_buffer("TestPolygons", "OBJECTID", 1000, 500, 45, "memory/test")

 

These are example buffers for a wind from the north east (azimuth = 45°):

JohannesLindner_0-1649079785478.png

 

Using appropriate major and minor distances according to wind speed would then be a problem of experience or calibration. Generally speaking:

  • low wind speed: major and minor distance are similar and relatively small
  • high wind speed: major distance is much greater that minor distance

 

Edit: For ArcMap, you have to replace all "memory" instances with "in_memory".


Have a great day!
Johannes