You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ArcGIS Pro 3.3 Notebook脚本优化:多边形贴合折线转角路径

ArcGIS Pro 3.3 Notebook Python脚本优化需求

现有脚本可生成以点为中心、与折线角度对齐的多边形,但在折线转角处,多边形无法贴合路径,需实现多边形随转角适配的效果。当前脚本可运行但未达预期,代码如下:

# Name:        Create Polygons at Points
# Purpose:     Create a polygon centered at each Structure and aligned with the angle of the polyline
# Created:     28/08/2024

import arcpy
import math

# Constants
WORKSPACE = r"PATH TO... Map.gdb"
STRUCTURES_LAYER_NAME = "Structures"
ALIGNMENT_LAYER_NAME = "Route"
OUTPUT_FC_NAME = "Aligned_Polygons"
TOLERANCE = 0.0125  # Updated tolerance

# Set workspace
arcpy.env.workspace = WORKSPACE

def get_map_by_name(aprx, map_name):
    """Retrieve a map by its name."""
    maps = aprx.listMaps(map_name)
    if not maps:
        raise RuntimeError(f"No map named '{map_name}' found in the current project.")
    return maps[0]

def get_layer_by_name(map_obj, layer_name):
    """Retrieve a layer by its name."""
    layers = map_obj.listLayers(layer_name)
    if not layers:
        raise RuntimeError(f"No layer named '{layer_name}' found in the map.")
    return layers[0]

def set_layer_visible_scale(layer):
    """Set the layer to be visible at all scales."""
    layer.minScale = 0
    layer.maxScale = 0
    print(f"Set layer '{layer.name}' to be visible at all scales.")

def create_output_feature_class(output_fc, spatial_ref):
    """Create the output feature class."""
    if arcpy.Exists(output_fc):
        arcpy.management.Delete(output_fc)
        print(f"Deleted existing feature class '{output_fc}'.")
    arcpy.management.CreateFeatureclass(arcpy.env.workspace, output_fc, "POLYGON", spatial_reference=spatial_ref)
    print(f"Output feature class '{output_fc}' created successfully.")

def add_fields_if_not_exist(output_fc, fields):
    """Add fields to the output feature class if they do not exist."""
    existing_fields = {f.name for f in arcpy.ListFields(output_fc)}
    for field_name, field_type in fields.items():
        if field_name not in existing_fields:
            arcpy.management.AddField(output_fc, field_name, field_type)
    print(f"Fields added to '{output_fc}'.")

def calculate_rotated_rectangle(center, width, height, angle):
    """Calculate a rotated rectangle's vertices."""
    angle_rad = math.radians(angle)
    dx = width / 2
    dy = height / 2
    corners = [(-dx, -dy), (dx, -dy), (dx, dy), (-dx, dy)]
    return [(center[0] + x * math.cos(angle_rad) - y * math.sin(angle_rad),
             center[1] + x * math.sin(angle_rad) + y * math.cos(angle_rad)) for x, y in corners]

def is_point_near_vertex(point, alignment_fc, tolerance=TOLERANCE):
    """Check if a point is near any vertex of the alignment features."""
    point_geom = arcpy.PointGeometry(arcpy.Point(*point))
    with arcpy.da.SearchCursor(alignment_fc, ["SHAPE@"]) as cursor:
        for row in cursor:
            geometry = row[0]
            if geometry:
                vertices = [arcpy.PointGeometry(pnt) for pnt in geometry.getPart(0)]
                if any(vertex.distanceTo(point_geom) <= tolerance for vertex in vertices):
                    return True
    return False

def main():
    # Prompt user for map name
    map_name = input("Enter the map name to use: ")
    # Prompt user for rectangle dimensions
    rectangle_length = float(input("Enter the rectangle length (in feet): "))
    rectangle_width = float(input("Enter the rectangle width (in feet): "))
    # Load the ArcGIS Project
    aprx = arcpy.mp.ArcGISProject("CURRENT")
    # Get the map and layers
    map_to_use = get_map_by_name(aprx, map_name)
    structures_layer = get_layer_by_name(map_to_use, STRUCTURES_LAYER_NAME)
    alignment_layer = get_layer_by_name(map_to_use, ALIGNMENT_LAYER_NAME)
    # Set layers to be visible at all scales
    set_layer_visible_scale(structures_layer)
    set_layer_visible_scale(alignment_layer)
    # Get feature class paths
    structures_fc = structures_layer.dataSource
    alignment_fc = alignment_layer.dataSource
    # Extract spatial reference
    spatial_ref = arcpy.Describe(structures_fc).spatialReference
    
    # Create output feature class
    output_fc = OUTPUT_FC_NAME
    create_output_feature_class(output_fc, spatial_ref)
    
    # Define fields to add
    fields_to_add = {
        "Length_ft": "DOUBLE",
        "Width_ft": "DOUBLE",
        "Unique_ID": "TEXT",
        "Type": "TEXT",
        "Feature": "TEXT",
        "Height": "DOUBLE",
        "County": "TEXT"
    }
    add_fields_if_not_exist(output_fc, fields_to_add)
    
    # Collect points data
    points_data = []
    with arcpy.da.SearchCursor(structures_fc, ["OBJECTID", "SHAPE@XY", "Unique_ID", "Type", "Feature", "Height", "County"], sql_clause=(None, 'ORDER BY OBJECTID')) as structures_cursor:
        for structure in structures_cursor:
            current_point = structure[1]
            if is_point_near_vertex(current_point, alignment_fc):
                points_data.append(structure[1:])  # Collect all attributes except OBJECTID
    
    # Create polygons
    with arcpy.da.InsertCursor(output_fc, ["SHAPE@", "Length_ft", "Width_ft", "Unique_ID", "Type", "Feature", "Height", "County"]) as insert_cursor:
        for i, data in enumerate(points_data):
            current_point, unique_id, type_field, feature, height, county = data
            angle = 0  # Default angle for the first point
            
            # Calculate angle for the first point
            if i == 0 and len(points_data) > 1:
                second_point = points_data[1][0]  # Get the second point's coordinates
                dx = second_point[0] - current_point[0]
                dy = second_point[1] - current_point[1]
                angle = math.degrees(math.atan2(dy, dx))
            
            # Calculate angle for all other points
            elif i > 0:
                previous_point = points_data[i - 1][0]  # Get the previous point's coordinates
                dx = current_point[0] - previous_point[0]
                dy = current_point[1] - previous_point[1]
                angle = math.degrees(math.atan2(dy, dx))
            
            # Calculate rectangle points centered on the current point
            rectangle = calculate_rotated_rectangle(current_point, rectangle_length, rectangle_width, angle)
            polygon = arcpy.Polygon(arcpy.Array([arcpy.Point(*coords) for coords in rectangle]), spatial_ref)
            insert_cursor.insertRow([polygon, rectangle_length, rectangle_width, unique_id, type_field, feature, height, county])
            print(f"Processed {i + 1} features...")
    
    print(f"Polygons created and saved in {output_fc}. Total features processed: {len(points_data)}.")

if __name__ == "__main__":
    main()

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 22:42:04