def adjustSpans(lc_scratch_ws, lc_catenary, lc_guide_lines, lc_adjust_all, lc_debug, lc_use_in_memory): try: # First, find the from and to points, and line number for this guide line. fieldList = ["FromTower", "ToTower", "LineNumber", "FromX", "FromY", "FromZ", "ToX", "ToY", "ToZ", "SagDistance", "WeightPerUnitLength"] fieldAccess = utils.FieldAccess(fieldList) # lc_guide_lines can be a layer. There is only 1 feature (selected) cursor = arcpy.da.SearchCursor(lc_guide_lines, fieldList) # Process selected guidelines. # XX Pretend for now that only one guideline is selected. index = 0 for row in cursor: # only one guideline is selected. if index == 0: fieldAccess.setRow(row) lineNumber = fieldAccess.getValue("LineNumber") fromTower = fieldAccess.getValue("FromTower") toTower = fieldAccess.getValue("ToTower") fromX = fieldAccess.getValue("FromX") fromY = fieldAccess.getValue("FromY") fromZ = fieldAccess.getValue("FromZ") toX = fieldAccess.getValue("ToX") toY = fieldAccess.getValue("ToY") toZ = fieldAccess.getValue("ToZ") sagDistance = fieldAccess.getValue("SagDistance") weightPerUnitLength = fieldAccess.getValue("WeightPerUnitLength") fromPointXYZ = vg.Point(fromX, fromY, fromZ) toPointXYZ = vg.Point(toX, toY, toZ) # Change to attachment point objects. fromPoint = create_3D_catenary.AttachmentPoint(fromPointXYZ, lineNumber, fromTower) toPoint = create_3D_catenary.AttachmentPoint(toPointXYZ, lineNumber, toTower) p("Initial sagDistance on feature:", sagDistance) # sag distance is None because we need to calculate it from the lineGuide # horizontal tension is not supplied. adjustedSpan = create_3D_catenary.makeSpan(fromPoint, toPoint, lc_guide_lines, weightPerUnitLength, None, None, None) newSpanDistance = adjustedSpan.sagDistance p("new sagDistance on feature:", newSpanDistance) if cursor: del cursor if lc_adjust_all: # We have already created the span with a sag distance. # For simplicity, we'll throw out that span object and make all six using that sag. adjustedSpans = [] fieldList = ["FromTower", "ToTower", "LineNumber", "FromX", "FromY", "FromZ", "ToX", "ToY", "ToZ"] fieldAccess = utils.FieldAccess(fieldList) whereClause = "FromTower = " + str(fromTower) + " and ToTower = " + str(toTower) p("sagDistance for all lines", newSpanDistance) # search in full feature class, not just selection i = 0 cursor = arcpy.da.SearchCursor(common_lib.get_full_path_from_layer(lc_guide_lines), fieldList, whereClause) for row in cursor: fieldAccess.setRow(row) lineNumber = fieldAccess.getValue("LineNumber") fromTower = fieldAccess.getValue("FromTower") toTower = fieldAccess.getValue("ToTower") fromX = fieldAccess.getValue("FromX") fromY = fieldAccess.getValue("FromY") fromZ = fieldAccess.getValue("FromZ") toX = fieldAccess.getValue("ToX") toY = fieldAccess.getValue("ToY") toZ = fieldAccess.getValue("ToZ") fromPointXYZ = vg.Point(fromX, fromY, fromZ) toPointXYZ = vg.Point(toX, toY, toZ) # Change to attachment point objects. fromPoint = create_3D_catenary.AttachmentPoint(fromPointXYZ, lineNumber, fromTower) toPoint = create_3D_catenary.AttachmentPoint(toPointXYZ, lineNumber, toTower) p("newSpanDistance in loop", newSpanDistance) adjustedSpan = create_3D_catenary.makeSpan(fromPoint, toPoint, common_lib.get_full_path_from_layer(lc_guide_lines), weightPerUnitLength, newSpanDistance, None) adjustedSpans.append(adjustedSpan) i+=1 # arcpy.AddMessage(str(i)) doSpanRemoveAndInsert(lc_catenary, common_lib.get_full_path_from_layer(lc_guide_lines), adjustedSpans) else: doSpanRemoveAndInsert(lc_catenary, common_lib.get_full_path_from_layer(lc_guide_lines), [adjustedSpan]) if lc_use_in_memory: arcpy.Delete_management("in_memory") if lc_debug == 0: fcs = common_lib.listFcsInGDB(lc_scratch_ws) msg_prefix = "Deleting intermediate data..." msg_body = common_lib.create_msg_body(msg_prefix, 0, 0) common_lib.msg(msg_body) for fc in fcs: arcpy.Delete_management(fc) arcpy.ClearWorkspaceCache_management() return lc_catenary, common_lib.get_full_path_from_layer(lc_guide_lines) except arcpy.ExecuteError: # Get the tool error messages msgs = arcpy.GetMessages(2) arcpy.AddError(msgs) except Exception: e = sys.exc_info()[1] arcpy.AddMessage("Unhandled exception: " + str(e.args[0])) pass
def main(): try: # Get Attributes from User if debugging == 0: # User input input_las_dataset = arcpy.GetParameterAsText(0) class_code = arcpy.GetParameter(1) cell_size = arcpy.GetParameterAsText(2) minimum_bridge_area = arcpy.GetParameterAsText(3) extrapolate_surface = arcpy.GetParameter(4) output_features = arcpy.GetParameterAsText(5) # script variables aprx = arcpy.mp.ArcGISProject("CURRENT") home_directory = aprx.homeFolder project_ws = aprx.defaultGeodatabase else: input_las_dataset = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\testing.lasd' class_code = 13 cell_size = str(0.5) minimum_bridge_area = str(20) extrapolate_surface = False output_features = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\Testing.gdb\bridges' home_directory = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact' project_ws = home_directory + "\\3DFloodImpact.gdb" if os.path.exists(home_directory + "\\p20"): # it is a package home_directory = home_directory + "\\p20" arcpy.AddMessage("Project Home Directory is: " + home_directory) # set directories layer_directory = home_directory + "\\layer_files" log_directory = home_directory + "\\Logs" if not os.path.exists(log_directory): os.makedirs(log_directory) # ensure numerical input is correct # fail safe for Europe's comma's cell_size = float(re.sub("[,.]", ".", cell_size)) minimum_bridge_area = float(re.sub("[,.]", ".", minimum_bridge_area)) # rename layer files (for packaging) if os.path.exists(layer_directory): common_lib.rename_file_extension(layer_directory, ".txt", ".lyrx") # Create folders and intermediate gdb, if needed scratch_ws = common_lib.create_gdb(home_directory, "Intermediate.gdb") arcpy.env.workspace = scratch_ws arcpy.env.overwriteOutput = True start_time = time.clock() # check if input exists if arcpy.Exists(input_las_dataset): # extract the elevation layers bridges = extract_bridges_from_las.extract( lc_lasd=input_las_dataset, lc_ws=scratch_ws, lc_class_code=class_code, lc_cell_size=float(cell_size), lc_min_bridge_area=float(minimum_bridge_area), lc_extrapolate=extrapolate_surface, lc_output_features=output_features, lc_log_dir=log_directory, lc_debug=verbose, lc_memory_switch=in_memory_switch) if bridges: if arcpy.Exists(bridges): arcpy.AddMessage("Adding Bridges") output_layer1 = common_lib.get_name_from_feature_class( bridges) arcpy.MakeFeatureLayer_management(bridges, output_layer1) arcpy.SetParameter(6, output_layer1) end_time = time.clock() msg_body = create_msg_body( "extract_bridges_from_las completed successfully.", start_time, end_time) msg(msg_body) else: end_time = time.clock() msg_body = create_msg_body( "No bridge surfaces created. Exiting...", start_time, end_time) msg(msg_body, WARNING) else: end_time = time.clock() msg_body = create_msg_body( "No bridge surfaces created. Exiting...", start_time, end_time) msg(msg_body, WARNING) arcpy.ClearWorkspaceCache_management() if DeleteIntermediateData: fcs = common_lib.listFcsInGDB(scratch_ws) rs = common_lib.list_rasters_in_gdb(scratch_ws, verbose) msg_prefix = "Deleting intermediate data..." msg_body = common_lib.create_msg_body(msg_prefix, 0, 0) common_lib.msg(msg_body) for fc in fcs: arcpy.Delete_management(fc) for r in rs: arcpy.Delete_management(r) # end main code except LicenseError3D: print("3D Analyst license is unavailable") arcpy.AddError("3D Analyst license is unavailable") except NoPointLayer: print("Can't find attachment points layer. Exiting...") arcpy.AddError("Can't find attachment points layer. Exiting...") except NoCatenaryLayer: print("Can't find Catenary layer. Exiting...") arcpy.AddError("Can't find Catenary layer. Exiting...") except NoCatenaryOutput: print("Can't create Catenary output. Exiting...") arcpy.AddError("Can't create Catenary output. Exiting...") except NoSwaySurfaceOutput: print("Can't find SwaySurface output. Exiting...") arcpy.AddError("Can't find SwaySurface. Exiting...") except NoGuideLinesLayer: print("Can't find GuideLines output. Exiting...") arcpy.AddError("Can't find GuideLines. Exiting...") except MoreThan1Selected: print( "More than 1 line selected. Please select 1 guide line only. Exiting..." ) arcpy.AddError( "More than 1 line selected. Please select 1 guide line only. Exiting..." ) except NoGuideLinesOutput: print("Can't create GuideLines output. Exiting...") arcpy.AddError("Can't create GuideLines. Exiting...") except arcpy.ExecuteError: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("With error message: %s" % synerror, ERROR) msg("ArcPy Error Message: %s" % arcpy.GetMessages(2), ERROR) except FunctionError as f_e: messages = f_e.args[0] msg("Error in function: %s" % messages["function"], ERROR) msg("Error on %s" % messages["line"], ERROR) msg("Error in file name: %s" % messages["filename"], ERROR) msg("With error message: %s" % messages["synerror"], ERROR) msg("ArcPy Error Message: %s" % messages["arc"], ERROR) except: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("with error message: %s" % synerror, ERROR) finally: arcpy.CheckInExtension("3D")
def main(): try: # Get Attributes from User if debugging == 0: # User input input_features = arcpy.GetParameterAsText(0) input_surface = arcpy.GetParameter(1) output_features = arcpy.GetParameterAsText(2) # script variables aprx = arcpy.mp.ArcGISProject("CURRENT") home_directory = aprx.homeFolder project_ws = aprx.defaultGeodatabase tin_directory = home_directory + "\TINs" else: input_features = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\Testing.gdb\bridges_test_surfaces' input_surface = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\ArcHydro\TSDepth\wse_28' output_features = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\Testing.gdb\bridges_HAS' home_directory = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact' project_ws = home_directory + "\\3DFloodImpact.gdb" tin_directory = home_directory + "\TINs" if os.path.exists(home_directory + "\\p20"): # it is a package home_directory = home_directory + "\\p20" if not os.path.exists(tin_directory): os.makedirs(tin_directory) arcpy.AddMessage("Project Home Directory is: " + home_directory) # set directories layer_directory = home_directory + "\\layer_files" log_directory = home_directory + "\\Logs" if not os.path.exists(log_directory): os.makedirs(log_directory) # rename layer files (for packaging) if os.path.exists(layer_directory): common_lib.rename_file_extension(layer_directory, ".txt", ".lyrx") # Create folders and intermediate gdb, if needed scratch_ws = common_lib.create_gdb(home_directory, "Intermediate.gdb") arcpy.env.workspace = scratch_ws arcpy.env.overwriteOutput = True start_time = time.clock() # check if input exists if arcpy.Exists(input_features): if arcpy.Exists(input_surface): z_values = arcpy.Describe(input_features).hasZ if z_values: # extract the elevation layers bridges, bridge_points = calculate_height_above_water_surface.calculate_height( lc_input_features=input_features, lc_ws=scratch_ws, lc_tin_dir=tin_directory, lc_input_surface=input_surface, lc_output_features=output_features, lc_log_dir=log_directory, lc_debug=verbose, lc_memory_switch=in_memory_switch) if bridges and bridge_points: # add symbology to points and add layer output_layer1 = common_lib.get_name_from_feature_class( bridges) arcpy.MakeFeatureLayer_management( bridges, output_layer1) output_layer2 = common_lib.get_name_from_feature_class( bridge_points) arcpy.MakeFeatureLayer_management( bridge_points, output_layer2) symbology_layer = layer_directory + "\\has_labels.lyrx" if arcpy.Exists(symbology_layer): arcpy.ApplySymbologyFromLayer_management( output_layer2, symbology_layer) else: msg_body = create_msg_body( "Can't find" + symbology_layer + " in " + layer_directory, 0, 0) msg(msg_body, WARNING) arcpy.SetParameter(3, output_layer1) arcpy.SetParameter(4, output_layer2) end_time = time.clock() msg_body = create_msg_body( "calculate_height_above_water_surface completed successfully.", start_time, end_time) msg(msg_body) else: end_time = time.clock() msg_body = create_msg_body( "No bridge surfaces and points created. Exiting...", start_time, end_time) msg(msg_body, WARNING) arcpy.ClearWorkspaceCache_management() if DeleteIntermediateData: fcs = common_lib.listFcsInGDB(scratch_ws) rs = common_lib.list_rasters_in_gdb( scratch_ws, verbose) msg_prefix = "Deleting intermediate data..." msg_body = common_lib.create_msg_body(msg_prefix, 0, 0) common_lib.msg(msg_body) for fc in fcs: arcpy.Delete_management(fc) for r in rs: arcpy.Delete_management(r) else: raise NoRaster else: raise No3DFeatures # end main code except No3DFeatures: # The input has no 3D features # print( '2D features are not supported. Make sure the input layer is a PolygonZ feature class.' ) arcpy.AddError( '2D features are not supported. Make sure the input layer is a PolygonZ feature class.' ) except NoRaster: # Can't find input raster # print("Can't find input raster.") arcpy.AddError("Can't find input raster.") except LicenseError3D: print("3D Analyst license is unavailable") arcpy.AddError("3D Analyst license is unavailable") except NoPointLayer: print("Can't find attachment points layer. Exiting...") arcpy.AddError("Can't find attachment points layer. Exiting...") except MoreThan1Selected: print( "More than 1 line selected. Please select 1 guide line only. Exiting..." ) arcpy.AddError( "More than 1 line selected. Please select 1 guide line only. Exiting..." ) except arcpy.ExecuteError: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("With error message: %s" % synerror, ERROR) msg("ArcPy Error Message: %s" % arcpy.GetMessages(2), ERROR) except FunctionError as f_e: messages = f_e.args[0] msg("Error in function: %s" % messages["function"], ERROR) msg("Error on %s" % messages["line"], ERROR) msg("Error in file name: %s" % messages["filename"], ERROR) msg("With error message: %s" % messages["synerror"], ERROR) msg("ArcPy Error Message: %s" % messages["arc"], ERROR) except: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("with error message: %s" % synerror, ERROR) finally: arcpy.CheckInExtension("3D")
def flood_from_raster(input_source, input_type, no_flood_value, baseline_elevation_raster, baseline_elevation_value, outward_buffer, output_polygons, smoothing, debug): try: # Get Attributes from User if debug == 0: # script variables aprx = arcpy.mp.ArcGISProject("CURRENT") home_directory = aprx.homeFolder tiff_directory = home_directory + "\\Tiffs" tin_directory = home_directory + "\\Tins" scripts_directory = aprx.homeFolder + "\\Scripts" rule_directory = aprx.homeFolder + "\\rule_packages" log_directory = aprx.homeFolder + "\\Logs" layer_directory = home_directory + "\\layer_files" project_ws = aprx.defaultGeodatabase enableLogging = True DeleteIntermediateData = True verbose = 0 use_in_memory = True else: # debug home_directory = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact' tiff_directory = home_directory + "\\Tiffs" tin_directory = home_directory + "\\Tins" scripts_directory = home_directory + "\\Scripts" rule_directory = home_directory + "\\rule_packages" log_directory = home_directory + "\\Logs" layer_directory = home_directory + "\\layer_files" project_ws = home_directory + "\\Results.gdb" enableLogging = False DeleteIntermediateData = True verbose = 1 use_in_memory = False scratch_ws = common_lib.create_gdb(home_directory, "Intermediate.gdb") arcpy.env.workspace = scratch_ws arcpy.env.overwriteOutput = True # fail safe for Europese's comma's baseline_elevation_value = float( re.sub("[,.]", ".", baseline_elevation_value)) if not os.path.exists(tiff_directory): os.makedirs(tiff_directory) if not os.path.exists(tin_directory): os.makedirs(tin_directory) common_lib.set_up_logging(log_directory, TOOLNAME) start_time = time.clock() if arcpy.CheckExtension("3D") == "Available": arcpy.CheckOutExtension("3D") if arcpy.CheckExtension("Spatial") == "Available": arcpy.CheckOutExtension("Spatial") flood_level_layer_mp = None desc = arcpy.Describe(input_source) arcpy.AddMessage( "Processing input source: " + common_lib.get_name_from_feature_class(input_source)) spatial_ref = desc.spatialReference # create IsNull to be used to clip and check for NoData. if use_in_memory: is_null0 = "in_memory/is_null0" else: is_null0 = os.path.join(scratch_ws, "is_null0") if arcpy.Exists(is_null0): arcpy.Delete_management(is_null0) is_null_raster = arcpy.sa.IsNull(input_source) is_null_raster.save(is_null0) if spatial_ref.type == 'PROJECTED' or spatial_ref.type == 'Projected': # check input source type: projected rasters ONLY!!!! # check type, if polygon -> convert to raster if input_type == "RasterLayer" or input_type == "RasterDataset" or input_type == "raster": # prep raster # smooth result using focal stats if smoothing > 0: if use_in_memory: focal_raster = "in_memory/focal_raster" else: focal_raster = os.path.join( scratch_ws, "focal_raster") if arcpy.Exists(focal_raster): arcpy.Delete_management(focal_raster) if not (1 <= smoothing <= 100): smoothing = 30 neighborhood = arcpy.sa.NbrRectangle( smoothing, smoothing, "CELL") flood_elev_raster = arcpy.sa.FocalStatistics( input_source, neighborhood, "MEAN", "true") flood_elev_raster.save(focal_raster) # con if use_in_memory: smooth_input = "in_memory/smooth_input" else: smooth_input = os.path.join( scratch_ws, "smooth_input") if arcpy.Exists(smooth_input): arcpy.Delete_management(smooth_input) output = arcpy.sa.Con(is_null0, input_source, flood_elev_raster) output.save(smooth_input) input_raster = smooth_input else: input_raster = input_source else: raise NotSupported # use numeric value for determining non flooded areas: set these values to NoData. We need NoData for clippng later on if no_flood_value != "NoData": if common_lib.is_number(no_flood_value): msg_body = create_msg_body( "Setting no flood value: " + no_flood_value + " to NoData in copy of " + common_lib.get_name_from_feature_class( input_raster) + "...", 0, 0) msg(msg_body) if use_in_memory: null_for_no_flooded_areas_raster = "in_memory/null_for_flooded" else: null_for_no_flooded_areas_raster = os.path.join( scratch_ws, "null_for_flooded") if arcpy.Exists( null_for_no_flooded_areas_raster): arcpy.Delete_management( null_for_no_flooded_areas_raster) whereClause = "VALUE = " + no_flood_value # Execute SetNull outSetNull_temp = arcpy.sa.SetNull( input_raster, input_raster, whereClause) outSetNull_temp.save( null_for_no_flooded_areas_raster) input_raster = null_for_no_flooded_areas_raster else: raise ValueError else: pass msg_body = create_msg_body( "Checking for NoData values in raster: " + common_lib.get_name_from_feature_class(input_raster) + ". NoData values are considered to be non-flooded areas!", 0, 0) msg(msg_body) max_value = arcpy.GetRasterProperties_management( is_null0, "MAXIMUM")[0] # has_nodata = arcpy.GetRasterProperties_management(input_raster, "ANYNODATA")[0] ## fails on some rasters if int(max_value) == 1: # 1. get the outline of the raster as polygon via RasterDomain xy_unit = common_lib.get_xy_unit(input_raster, 0) if xy_unit: cell_size = arcpy.GetRasterProperties_management( input_raster, "CELLSIZEX") if baseline_elevation_raster: # check celll size cell_size_base = arcpy.GetRasterProperties_management( baseline_elevation_raster, "CELLSIZEX") if cell_size_base.getOutput( 0) == cell_size.getOutput(0): # Execute Plus if use_in_memory: flood_plus_base_raster = "in_memory/flooding_plus_base" else: flood_plus_base_raster = os.path.join( scratch_ws, "flooding_plus_base") if arcpy.Exists( flood_plus_base_raster): arcpy.Delete_management( flood_plus_base_raster) listRasters = [] listRasters.append(input_raster) listRasters.append( baseline_elevation_raster) desc = arcpy.Describe(listRasters[0]) arcpy.MosaicToNewRaster_management( listRasters, scratch_ws, "flooding_plus_base", desc.spatialReference, "32_BIT_FLOAT", cell_size, 1, "SUM", "") # check where there is IsNull and set the con values if use_in_memory: is_Null = "in_memory/is_Null" else: is_Null = os.path.join( scratch_ws, "is_Null") if arcpy.Exists(is_Null): arcpy.Delete_management(is_Null) is_Null_raster = arcpy.sa.IsNull( input_raster) is_Null_raster.save(is_Null) # Con if use_in_memory: flood_plus_base_raster_null = "in_memory/flooding_plus_base_null" else: flood_plus_base_raster_null = os.path.join( scratch_ws, "flooding_plus_base_null") if arcpy.Exists( flood_plus_base_raster_null): arcpy.Delete_management( flood_plus_base_raster_null) msg_body = create_msg_body( "Adding baseline elevation raster to input flood layer...", 0, 0) msg(msg_body) fpbrn = arcpy.sa.Con( is_Null, input_raster, flood_plus_base_raster) fpbrn.save(flood_plus_base_raster_null) input_raster = flood_plus_base_raster_null else: arcpy.AddWarning( "Cell size of " + input_raster + " is different than " + baseline_elevation_raster + ". Ignoring Base Elevation Raster.") else: if baseline_elevation_value > 0: if use_in_memory: flood_plus_base_raster = "in_memory/flood_plus_base" else: flood_plus_base_raster = os.path.join( scratch_ws, "flooding_plus_base") if arcpy.Exists( flood_plus_base_raster): arcpy.Delete_management( flood_plus_base_raster) arcpy.Plus_3d(input_raster, baseline_elevation_value, flood_plus_base_raster) input_raster = flood_plus_base_raster msg_body = create_msg_body( "Creating 3D polygons...", 0, 0) msg(msg_body) if use_in_memory: raster_polygons = "in_memory/raster_polygons" else: raster_polygons = os.path.join( scratch_ws, "raster_polygons") if arcpy.Exists(raster_polygons): arcpy.Delete_management(raster_polygons) out_geom = "POLYGON" # output geometry type arcpy.RasterDomain_3d(input_raster, raster_polygons, out_geom) # 2. buffer it inwards so that we have a polygon only of the perimeter plus a few ???????cells inward???????. if use_in_memory: polygons_inward = "in_memory/inward_buffer" else: polygons_inward = os.path.join( scratch_ws, "inward_buffer") if arcpy.Exists(polygons_inward): arcpy.Delete_management(polygons_inward) x = float( re.sub("[,.]", ".", str(cell_size.getOutput(0)))) # x = float(str(cell_size.getOutput(0))) if x < 0.1: arcpy.AddError( "Raster cell size is 0. Can't continue. Please check the raster properties." ) raise ValueError else: buffer_in = 3 * int(x) if xy_unit == "Feet": buffer_text = "-" + str( buffer_in) + " Feet" else: buffer_text = "-" + str( buffer_in) + " Meters" sideType = "OUTSIDE_ONLY" arcpy.Buffer_analysis(raster_polygons, polygons_inward, buffer_text, sideType) msg_body = create_msg_body( "Buffering flood edges...", 0, 0) msg(msg_body) # 3. mask in ExtractByMask: gives just boundary raster with a few cells inwards if use_in_memory: extract_mask_raster = "in_memory/extract_mask" else: extract_mask_raster = os.path.join( scratch_ws, "extract_mask") if arcpy.Exists(extract_mask_raster): arcpy.Delete_management( extract_mask_raster) extract_temp_raster = arcpy.sa.ExtractByMask( input_raster, polygons_inward) extract_temp_raster.save(extract_mask_raster) # 4. convert the output to points if use_in_memory: extract_mask_points = "in_memory/extract_points" else: extract_mask_points = os.path.join( scratch_ws, "extract_points") if arcpy.Exists(extract_mask_points): arcpy.Delete_management( extract_mask_points) arcpy.RasterToPoint_conversion( extract_mask_raster, extract_mask_points, "VALUE") msg_body = create_msg_body( "Create flood points...", 0, 0) msg(msg_body) # 5. Interpolate: this will also interpolate outside the flood boundary which is # what we need so we get a nice 3D poly that extends into the surrounding DEM if use_in_memory: interpolated_raster = "in_memory/interpolate_raster" else: interpolated_raster = os.path.join( scratch_ws, "interpolate_raster") if arcpy.Exists(interpolated_raster): arcpy.Delete_management( interpolated_raster) zField = "grid_code" power = 2 searchRadius = arcpy.sa.RadiusVariable( 12, 150000) msg_body = create_msg_body( "Interpolating flood points...", 0, 0) msg(msg_body) # Execute IDW out_IDW = arcpy.sa.Idw(extract_mask_points, zField, cell_size, power) # Save the output out_IDW.save(interpolated_raster) extent_poly = common_lib.get_extent_feature( scratch_ws, polygons_inward) msg_body = create_msg_body( "Clipping terrain...", 0, 0) msg(msg_body) # clip the input surface if use_in_memory: extent_clip_idwraster = "in_memory/extent_clip_idw" else: extent_clip_idwraster = os.path.join( scratch_ws, "extent_clip_idw") if arcpy.Exists(extent_clip_idwraster): arcpy.Delete_management( extent_clip_idwraster) # clip terrain to extent arcpy.Clip_management(interpolated_raster, "#", extent_clip_idwraster, extent_poly) # 6. clip the interpolated raster by (outward buffered) outline polygon if use_in_memory: polygons_outward = "in_memory/outward_buffer" else: polygons_outward = os.path.join( scratch_ws, "outward_buffer") if arcpy.Exists(polygons_outward): arcpy.Delete_management( polygons_outward) outward_buffer += 0.5 * int( x ) # we buffer out by half the raster cellsize if outward_buffer > 0: if xy_unit == "Feet": buffer_text = str( outward_buffer) + " Feet" else: buffer_text = str( outward_buffer) + " Meters" sideType = "FULL" arcpy.Buffer_analysis( raster_polygons, polygons_outward, buffer_text, sideType) raster_polygons = polygons_outward # clip the input surface if use_in_memory: flood_clip_raster = "in_memory/flood_clip_raster" else: flood_clip_raster = os.path.join( scratch_ws, "flood_clip_raster") if arcpy.Exists(flood_clip_raster): arcpy.Delete_management( flood_clip_raster) msg_body = create_msg_body( "Clipping flood raster...", 0, 0) msg(msg_body) # clip terrain to extent # arcpy.Clip_management(interpolated_raster, "#", flood_clip_raster, raster_polygons) Check again arcpy.Clip_management(interpolated_raster, "#", flood_clip_raster, raster_polygons) # 7. Isnull, and Con to grab values from flood_clip_raster for # create NUll mask if use_in_memory: is_Null = "in_memory/is_Null" else: is_Null = os.path.join( scratch_ws, "is_Null") if arcpy.Exists(is_Null): arcpy.Delete_management(is_Null) is_Null_raster = arcpy.sa.IsNull(input_raster) is_Null_raster.save(is_Null) # Con if use_in_memory: con_raster = "in_memory/con_raster" else: con_raster = os.path.join( scratch_ws, "con_raster") if arcpy.Exists(con_raster): arcpy.Delete_management(con_raster) temp_con_raster = arcpy.sa.Con( is_Null, interpolated_raster, input_raster) temp_con_raster.save(con_raster) msg_body = create_msg_body( "Merging rasters...", 0, 0) msg(msg_body) # 8. focal stats on raster to smooth? # 9. copy raster to geotiff if use_in_memory: con_raster_tif = "in_memory/con_raster_tif" else: con_raster_tif = os.path.join( tiff_directory, "con_raster.tif") if arcpy.Exists(con_raster_tif): arcpy.Delete_management(con_raster_tif) arcpy.CopyRaster_management( con_raster, con_raster_tif, "#", "#", "#", "#", "#", "32_BIT_FLOAT") msg_body = create_msg_body( "Copying to tiff...", 0, 0) msg(msg_body) # 10. raster to TIN zTol = 0.1 maxPts = 1500000 zFactor = 1 con_tin = os.path.join(tin_directory, "con_tin") if arcpy.Exists(con_tin): arcpy.Delete_management(con_tin) # Execute RasterTin arcpy.RasterTin_3d(con_raster_tif, con_tin, zTol, maxPts, zFactor) msg_body = create_msg_body( "Creating TIN...", 0, 0) msg(msg_body) # 11. TIN triangles if use_in_memory: con_triangles = "in_memory/con_triangles" else: con_triangles = os.path.join( scratch_ws, "con_triangles") if arcpy.Exists(con_triangles): arcpy.Delete_management(con_triangles) arcpy.TinTriangle_3d(con_tin, con_triangles) msg_body = create_msg_body( "Creating polygons...", 0, 0) msg(msg_body) # 12. make 2D polygons feature to feature class arcpy.FeatureClassToFeatureClass_conversion( con_triangles, scratch_ws, "con_triangles_2D") # 12. clip with smooth polygon smooth_polygons = os.path.join( scratch_ws, "smooth_raster_polygons") if arcpy.Exists(smooth_polygons): arcpy.Delete_management(smooth_polygons) msg_body = create_msg_body( "Smoothing edges...", 0, 0) msg(msg_body) CA.SmoothPolygon(os.path.join(raster_polygons), smooth_polygons, "PAEK", x, "", "FLAG_ERRORS") if use_in_memory: clip_smooth_triangles = "in_memory/clip_smooth_triangles" else: clip_smooth_triangles = os.path.join( scratch_ws, "clip_smooth_triangles") if arcpy.Exists(clip_smooth_triangles): arcpy.Delete_management( clip_smooth_triangles) msg_body = create_msg_body( "Clipping smooth edges...", 0, 0) msg(msg_body) # clip terrain to extent arcpy.Clip_analysis(con_triangles, smooth_polygons, clip_smooth_triangles) # clip to slightly lesser extent because of InterpolateShape fail. area_extent = common_lib.get_extent_feature( scratch_ws, clip_smooth_triangles) if use_in_memory: extent_inward = "in_memory/inward_extent_buffer" else: extent_inward = os.path.join( scratch_ws, "inward_extent_buffer") if arcpy.Exists(extent_inward): arcpy.Delete_management(extent_inward) buffer_in = 3 if xy_unit == "Feet": buffer_text = "-" + str( buffer_in) + " Feet" else: buffer_text = "-" + str( buffer_in) + " Meters" sideType = "FULL" arcpy.Buffer_analysis(area_extent, extent_inward, buffer_text, sideType) if use_in_memory: clip2_smooth_triangles = "in_memory/clip2_smooth_triangles" else: clip2_smooth_triangles = os.path.join( scratch_ws, "clip2_smooth_triangles") if arcpy.Exists(clip2_smooth_triangles): arcpy.Delete_management( clip2_smooth_triangles) msg_body = create_msg_body( "Clipping smooth edges a second time...", 0, 0) msg(msg_body) # clip terrain to extent arcpy.Clip_analysis(clip_smooth_triangles, extent_inward, clip2_smooth_triangles) # 13. interpolate on TIN if use_in_memory: clip_smooth_triangles3D = "in_memory/clip_smooth_traingles3D" else: clip_smooth_triangles3D = os.path.join( scratch_ws, "clip_smooth_triangles3D") if arcpy.Exists(clip_smooth_triangles3D): arcpy.Delete_management( clip_smooth_triangles3D) msg_body = create_msg_body( "Interpolating polygons on TIN", 0, 0) msg(msg_body) arcpy.InterpolateShape_3d( con_tin, clip2_smooth_triangles, clip_smooth_triangles3D, "#", 1, "LINEAR", "VERTICES_ONLY") # 13. to multipatch z_unit = common_lib.get_z_unit( clip_smooth_triangles3D, verbose) # temp layer flood_level_layer = "flood_level_layer" arcpy.MakeFeatureLayer_management( clip_smooth_triangles3D, flood_level_layer) # flood_level_mp = os.path.join(project_ws, common_lib.get_name_from_feature_class(input_raster) + "_3D") flood_level_mp = output_polygons + "_3D" if arcpy.Exists(flood_level_mp): arcpy.Delete_management(flood_level_mp) arcpy.Layer3DToFeatureClass_3d( flood_level_layer, flood_level_mp) # layer to be added to TOC flood_level_layer_mp = common_lib.get_name_from_feature_class( flood_level_mp) arcpy.MakeFeatureLayer_management( flood_level_mp, flood_level_layer_mp) # apply transparency here // checking if symbology layer is present if z_unit == "Feet": floodSymbologyLayer = layer_directory + "\\flood3Dfeet.lyrx" else: floodSymbologyLayer = layer_directory + "\\flood3Dmeter.lyrx" if not arcpy.Exists(floodSymbologyLayer): arcpy.AddWarning( "Can't find: " + floodSymbologyLayer + ". Symbolize features by error attribute to see data errors." ) arcpy.AddMessage("Results written to: " + output_polygons) if use_in_memory: arcpy.Delete_management("in_memory") if DeleteIntermediateData: fcs = common_lib.listFcsInGDB(scratch_ws) msg_prefix = "Deleting intermediate data..." msg_body = common_lib.create_msg_body( msg_prefix, 0, 0) common_lib.msg(msg_body) for fc in fcs: arcpy.Delete_management(fc) return flood_level_layer_mp # 14. adjust 3D Z feet to meters??? else: raise NoUnits else: raise NoNoDataError end_time = time.clock() msg_body = create_msg_body( "Create 3D Flood Leveles completed successfully.", start_time, end_time) else: raise NotProjected else: raise LicenseErrorSpatial else: raise LicenseError3D arcpy.ClearWorkspaceCache_management() msg(msg_body) except NotProjected: print( "Input data needs to be in a projected coordinate system. Exiting..." ) arcpy.AddError( "Input data needs to be in a projected coordinate system. Exiting..." ) except NoLayerFile: print("Can't find Layer file. Exiting...") arcpy.AddError("Can't find Layer file. Exiting...") except LicenseError3D: print("3D Analyst license is unavailable") arcpy.AddError("3D Analyst license is unavailable") except LicenseErrorSpatial: print("Spatial Analyst license is unavailable") arcpy.AddError("Spatial Analyst license is unavailable") except NoNoDataError: print("Input raster does not have NODATA values") arcpy.AddError("Input raster does not have NODATA values") except NoUnits: print("No units detected on input data") arcpy.AddError("No units detected on input data") except NoPolygons: print("Input data can only be polygon features or raster datasets.") arcpy.AddError( "Input data can only be polygon features or raster datasets.") except ValueError: print("Input no flood value is not a number.") arcpy.AddError("Input no flood value is not a number.") except arcpy.ExecuteError: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("With error message: %s" % synerror, ERROR) msg("ArcPy Error Message: %s" % arcpy.GetMessages(2), ERROR) except FunctionError as f_e: messages = f_e.args[0] msg("Error in function: %s" % messages["function"], ERROR) msg("Error on %s" % messages["line"], ERROR) msg("Error in file name: %s" % messages["filename"], ERROR) msg("With error message: %s" % messages["synerror"], ERROR) msg("ArcPy Error Message: %s" % messages["arc"], ERROR) except: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("with error message: %s" % synerror, ERROR) finally: arcpy.CheckInExtension("3D") arcpy.CheckInExtension("Spatial")
def main(): try: # Get Attributes from User if debugging == 0: ## User input input_source = arcpy.GetParameter(0) angle = arcpy.GetParameterAsText(1) output_features = arcpy.GetParameterAsText(2) # script variables aprx = arcpy.mp.ArcGISProject("CURRENT") home_directory = aprx.homeFolder layer_directory = home_directory + "\\layer_files" rule_directory = aprx.homeFolder + "\\rule_packages" log_directory = aprx.homeFolder + "\\Logs" project_ws = aprx.defaultGeodatabase else: # debug input_source = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.2.3\Transmission_Lines\Testing.gdb\Cat_test_LineGuides_3D' angle = 45 output_features = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.2.3\Transmission_Lines\Testing.gdb\sway_surfaces' home_directory = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.2.3\Transmission_Lines' layer_directory = home_directory + "\\layer_files" rule_directory = home_directory + "\\rule_packages" log_directory = home_directory + "\\Logs" project_ws = home_directory + "\\\Transmission_Lines.gdb" scratch_ws = common_lib.create_gdb(home_directory, "Intermediate.gdb") arcpy.env.workspace = scratch_ws arcpy.env.overwriteOutput = True start_time = time.clock() # check if input exists if arcpy.Exists(input_source): # make a copy to grab the selection input_source_copy = os.path.join(scratch_ws, "catenary_copy") if arcpy.Exists(input_source_copy): arcpy.Delete_management(input_source_copy) arcpy.CopyFeatures_management(input_source, input_source_copy) # check number of selected features num_features = int( arcpy.GetCount_management(input_source_copy).getOutput(0)) if num_features == 1: arcpy.AddMessage( "Creating sway surface for selected catenary: " + common_lib.get_name_from_feature_class(input_source)) else: arcpy.AddMessage( "Creating multiple sway surfaces for catenaries: " + common_lib.get_name_from_feature_class(input_source)) sway_lines, sway_surfaces = create_3D_swaysurface.makeSwayLinesAndSurfaces( lc_scratch_ws=scratch_ws, lc_catenary=input_source_copy, lc_angle=int(angle), lc_output_features=output_features, lc_debug=verbose, lc_use_in_memory=False) end_time = time.clock() if sway_lines and sway_surfaces: if arcpy.Exists(sway_lines) and arcpy.Exists(sway_surfaces): # create layer, set layer file # apply transparency here // checking if symbology layer is present z_unit = common_lib.get_z_unit(sway_surfaces, verbose) if z_unit == "Feet": swaysurfaceSymbologyLayer = layer_directory + "\\swaysurface3Dfeet_mp.lyrx" else: swaysurfaceSymbologyLayer = layer_directory + "\\swaysurface3Dmeter_mp.lyrx" sway_layer = common_lib.get_name_from_feature_class( sway_surfaces) arcpy.MakeFeatureLayer_management(sway_surfaces, sway_layer) sway_surfaces_mp = output_features + "_3D" if arcpy.Exists(sway_surfaces_mp): arcpy.Delete_management(sway_surfaces_mp) arcpy.Layer3DToFeatureClass_3d(sway_layer, sway_surfaces_mp, "LineNumber") output_layer3 = common_lib.get_name_from_feature_class( sway_surfaces_mp) arcpy.MakeFeatureLayer_management(sway_surfaces_mp, output_layer3) if arcpy.Exists(swaysurfaceSymbologyLayer): arcpy.ApplySymbologyFromLayer_management( output_layer3, swaysurfaceSymbologyLayer) else: msg_body = create_msg_body( "Can't find" + swaysurfaceSymbologyLayer + " in " + layer_directory, 0, 0) msg(msg_body, WARNING) if output_layer3: if z_unit == "Feet": arcpy.SetParameter(3, output_layer3) else: arcpy.SetParameter(4, output_layer3) else: raise NoSwaySurfaceOutput else: end_time = time.clock() msg_body = create_msg_body( "No sway lines or surfaces created. Exiting...", start_time, end_time) msg(msg_body, WARNING) else: end_time = time.clock() msg_body = create_msg_body( "No sway lines or surfaces created. Exiting...", start_time, end_time) msg(msg_body, WARNING) arcpy.ClearWorkspaceCache_management() if DeleteIntermediateData: fcs = common_lib.listFcsInGDB(scratch_ws) msg_prefix = "Deleting intermediate data..." msg_body = common_lib.create_msg_body(msg_prefix, 0, 0) common_lib.msg(msg_body) for fc in fcs: arcpy.Delete_management(fc) # end main code except LicenseError3D: print("3D Analyst license is unavailable") arcpy.AddError("3D Analyst license is unavailable") except NoPointLayer: print("Can't find attachment points layer. Exiting...") arcpy.AddError("Can't find attachment points layer. Exiting...") except NoPointLayer: print( "None or more than 1 guide line selected. Please select only 1 guide line. Exiting..." ) arcpy.AddError( "None or more than 1 guide line selected. Please select only 1 guide line. Exiting..." ) except NoCatenaryLayer: print("Can't find Catenary layer. Exiting...") arcpy.AddError("Can't find Catenary layer. Exiting...") except NoCatenaryOutput: print("Can't create Catenary output. Exiting...") arcpy.AddError("Can't create Catenary output. Exiting...") except NoSwaySurfaceOutput: print("Can't find SwaySurface output. Exiting...") arcpy.AddError("Can't find SwaySurface. Exiting...") except NoGuideLinesLayer: print("Can't find GuideLines output. Exiting...") arcpy.AddError("Can't find GuideLines. Exiting...") except MoreThan1Selected: print( "More than 1 line selected. Please select 1 guide line only. Exiting..." ) arcpy.AddError( "More than 1 line selected. Please select 1 guide line only. Exiting..." ) except NoGuideLinesOutput: print("Can't create GuideLines output. Exiting...") arcpy.AddError("Can't create GuideLines. Exiting...") except arcpy.ExecuteError: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("With error message: %s" % synerror, ERROR) msg("ArcPy Error Message: %s" % arcpy.GetMessages(2), ERROR) except FunctionError as f_e: messages = f_e.args[0] msg("Error in function: %s" % messages["function"], ERROR) msg("Error on %s" % messages["line"], ERROR) msg("Error in file name: %s" % messages["filename"], ERROR) msg("With error message: %s" % messages["synerror"], ERROR) msg("ArcPy Error Message: %s" % messages["arc"], ERROR) except: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("with error message: %s" % synerror, ERROR) finally: arcpy.CheckInExtension("3D")
def makeSpans(lc_scratch_ws, lc_inPoints, lc_testLineWeight, lc_sag_to_span_ratio, lc_horizontal_tension, lc_output_features, lc_debug, lc_use_in_memory, lc_cleanup, lc_caller): try: geometry_type = "POLYLINE" has_m = "DISABLED" has_z = "ENABLED" from_tower_field = "FromTower" to_tower_field = "ToTower" line_number_field = "LineNumber" count_field = "COUNT" from_X_field = "FromX" from_Y_field = "FromY" from_Z_field = "FromZ" To_X_field = "ToX" To_Y_field = "ToY" To_Z_field = "ToZ" sag_distance = "SagDistance" horizontal_tension = "HorizontalTension" line_lenght = "LineLength" weight_per_unit_length = "WeightPerUnitLength" transmission_line_name = "TransmissionLines3D" transmission_guide_name = "TransmissionLineGuide" in_memory = "in_memory" spatial_reference = arcpy.Describe(lc_inPoints).spatialReference # create empty feature class with required fields # msg_body = create_msg_body("Preparing output feature classes...", 0, 0) # msg(msg_body) if lc_use_in_memory: arcpy.AddMessage("Using in memory for processing") includedTransmissionLinesFC = in_memory + "/" + transmission_line_name arcpy.CreateFeatureclass_management(in_memory, transmission_line_name, geometry_type, "", has_m, has_z, spatial_reference) else: includedTransmissionLinesFC = lc_output_features + "_3D" includedTransmissionLinesFC_dirname = os.path.dirname(includedTransmissionLinesFC) includedTransmissionLinesFC_basename = os.path.basename(includedTransmissionLinesFC) if arcpy.Exists(includedTransmissionLinesFC): arcpy.Delete_management(includedTransmissionLinesFC) arcpy.CreateFeatureclass_management(includedTransmissionLinesFC_dirname, includedTransmissionLinesFC_basename, geometry_type, "", has_m, has_z, spatial_reference) fields1_dict = {from_tower_field:"LONG", to_tower_field:"LONG", line_number_field:"LONG", count_field:"LONG", sag_distance:"DOUBLE", horizontal_tension:"DOUBLE", line_lenght:"DOUBLE", weight_per_unit_length:"DOUBLE" } listoffields1 = [] for k, v in fields1_dict.items(): field = [] field.append(k) field.append(v) listoffields1.append(field) arcpy.management.AddFields(includedTransmissionLinesFC, listoffields1) # common_lib.delete_add_field(includedTransmissionLinesFC, from_tower_field, "LONG") # common_lib.delete_add_field(includedTransmissionLinesFC, to_tower_field, "LONG") # common_lib.delete_add_field(includedTransmissionLinesFC, line_number_field, "LONG") # common_lib.delete_add_field(includedTransmissionLinesFC, count_field, "LONG") # common_lib.delete_add_field(includedTransmissionLinesFC, sag_distance, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLinesFC, horizontal_tension, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLinesFC, line_lenght, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLinesFC, weight_per_unit_length, "DOUBLE") if lc_caller == "Create3Dcatenaryfromline": create_guidelines = False else: create_guidelines = True if create_guidelines: if lc_use_in_memory: includedTransmissionLineGuides = in_memory + "/" + transmission_guide_name arcpy.CreateFeatureclass_management(in_memory, transmission_guide_name, geometry_type, "", has_m, has_z, spatial_reference) else: includedTransmissionLineGuides = lc_output_features + "_LineGuides_3D" includedTransmissionLinesGuides_dirname = os.path.dirname(includedTransmissionLineGuides) includedTransmissionLinesGuides_basename = os.path.basename(includedTransmissionLineGuides) if arcpy.Exists(includedTransmissionLineGuides): arcpy.Delete_management(includedTransmissionLineGuides) arcpy.CreateFeatureclass_management(includedTransmissionLinesGuides_dirname, includedTransmissionLinesGuides_basename, geometry_type, "", has_m, has_z, spatial_reference) fields2_dict = {from_tower_field: "LONG", to_tower_field: "LONG", line_number_field: "LONG", from_X_field: "DOUBLE", from_Y_field: "DOUBLE", from_Z_field: "DOUBLE", To_X_field: "DOUBLE", To_Y_field: "DOUBLE", To_Z_field: "DOUBLE", count_field: "LONG", sag_distance: "DOUBLE", weight_per_unit_length: "DOUBLE" } listoffields2 = [] for k, v in fields2_dict.items(): field = [] field.append(k) field.append(v) listoffields2.append(field) arcpy.management.AddFields(includedTransmissionLineGuides, listoffields2) # common_lib.delete_add_field(includedTransmissionLineGuides, from_tower_field, "LONG") # common_lib.delete_add_field(includedTransmissionLineGuides, to_tower_field, "LONG") # common_lib.delete_add_field(includedTransmissionLineGuides, line_number_field, "LONG") # common_lib.delete_add_field(includedTransmissionLineGuides, from_X_field, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLineGuides, from_Y_field, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLineGuides, from_Z_field, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLineGuides, To_X_field, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLineGuides, To_Y_field, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLineGuides, To_Z_field, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLineGuides, sag_distance, "DOUBLE") # common_lib.delete_add_field(includedTransmissionLineGuides, weight_per_unit_length, "DOUBLE") else: includedTransmissionLineGuides = None ############################################################################################### Chris continues................... attachmentPointList = [] fieldList = ["SHAPE@X", "SHAPE@Y", "SHAPE@Z", "Line", "Tower"] fieldAccess = utils.FieldAccess(fieldList) cursor = arcpy.da.SearchCursor(lc_inPoints, fieldList) for row in cursor: fieldAccess.setRow(row) x = fieldAccess.getValue("SHAPE@X") y = fieldAccess.getValue("SHAPE@Y") z = fieldAccess.getValue("SHAPE@Z") lineNumber = fieldAccess.getValue("Line") towerNumber = fieldAccess.getValue("Tower") point = vg.Point(x, y, z) attachmentPoint = AttachmentPoint(point, lineNumber, towerNumber) attachmentPointList.append(attachmentPoint) if cursor: del cursor # Organize points into lists per line. dictionaryOfListsOfAttachmentPointsPerLine = {} for attachmentPoint in attachmentPointList: lineNumber = attachmentPoint.lineNumber if lineNumber in dictionaryOfListsOfAttachmentPointsPerLine.keys(): listOfAttachmentPointsPerLine = dictionaryOfListsOfAttachmentPointsPerLine[lineNumber] else: listOfAttachmentPointsPerLine = [] dictionaryOfListsOfAttachmentPointsPerLine[lineNumber] = listOfAttachmentPointsPerLine listOfAttachmentPointsPerLine.append(attachmentPoint) # Sort attachment points in each line list. # And make a list of line numbers for use in another dictionary. dictionaryOfSpanListsPerLine = {} lineNumberList = [] for lineNumber in dictionaryOfListsOfAttachmentPointsPerLine.keys(): lineNumberList.append(lineNumber) listOfAttachmentPointsPerLine = dictionaryOfListsOfAttachmentPointsPerLine[lineNumber] listOfAttachmentPointsPerLineSorted = sorted(listOfAttachmentPointsPerLine, key=lambda attachmentPoint: attachmentPoint.towerNumber) spanListPerThisLine = [] for index in range(0, len(listOfAttachmentPointsPerLineSorted) - 1): fromPoint = listOfAttachmentPointsPerLineSorted[index] toPoint = listOfAttachmentPointsPerLineSorted[index + 1] # This is to give shield wires less sag, but only works when using the Easy Way. sagToSpanRatioForMakeSpan = None if lc_sag_to_span_ratio is not None: sagToSpanRatioForMakeSpan = lc_sag_to_span_ratio if lineNumber < 0: sagToSpanRatioForMakeSpan = sagToSpanRatioForMakeSpan * 0.5 span = makeSpan(fromPoint, toPoint, includedTransmissionLineGuides, lc_testLineWeight, sagToSpanRatio=sagToSpanRatioForMakeSpan,sagDistance=None, horizontalTension=lc_horizontal_tension) spanListPerThisLine.append(span) dictionaryOfSpanListsPerLine[lineNumber] = spanListPerThisLine # msg_body = create_msg_body("Writing all span lines to " + includedTransmissionLinesFC_basename + ".", 0, 0) # msg(msg_body) for index in range(0,len(lineNumberList)): lineNumber = lineNumberList[index] spanListPerThisLine = dictionaryOfSpanListsPerLine[lineNumber] # not TODO: CW, yes is has to run: switch is driven by includedTransmissionLineGuides inside the function. doInsertSpanAndGuideLine(includedTransmissionLinesFC, includedTransmissionLineGuides, spanListPerThisLine) if includedTransmissionLineGuides is not None: # not TODO: CW, nope: see inside doInsertSpanAndGuideLine but could be coded more elegantly msg_body = create_msg_body( "Created helper Guide Lines feature class " + common_lib.get_name_from_feature_class(includedTransmissionLineGuides) + ".", 0, 0) msg(msg_body) # TODO check when necessary. When called from create_3D_catenary_from_line, this should not be called. if lc_cleanup: if lc_use_in_memory: arcpy.Delete_management("in_memory") if lc_debug == 0: fcs = common_lib.listFcsInGDB(lc_scratch_ws) msg_prefix = "Deleting intermediate data..." msg_body = common_lib.create_msg_body(msg_prefix, 0, 0) common_lib.msg(msg_body) for fc in fcs: arcpy.Delete_management(fc) arcpy.ClearWorkspaceCache_management() return includedTransmissionLinesFC, includedTransmissionLineGuides except arcpy.ExecuteError: # Get the tool error messages msgs = arcpy.GetMessages(2) arcpy.AddError(msgs) except Exception: e = sys.exc_info()[1] arcpy.AddMessage("Unhandled exception: " + str(e.args[0])) pass
def main(): try: # Get Attributes from User if debugging == 0: ## User input input_features = arcpy.GetParameterAsText(0) tower_height = arcpy.GetParameterAsText(1) voltage = arcpy.GetParameterAsText(2) do_sag_to_span = arcpy.GetParameter(3) conductor_name = arcpy.GetParameterAsText(4) horizontal_tension = arcpy.GetParameter(7) output_features = arcpy.GetParameterAsText(8) structure_type = arcpy.GetParameterAsText(13) circuits = arcpy.GetParameterAsText(14) alignment = arcpy.GetParameterAsText(15) insulator_hang_type = arcpy.GetParameterAsText(16) shield_wires = arcpy.GetParameterAsText(17) line_type = arcpy.GetParameterAsText(19) tower_material = arcpy.GetParameterAsText(20) endPoints = arcpy.GetParameterAsText(21) # script variables aprx = arcpy.mp.ArcGISProject("CURRENT") home_directory = aprx.homeFolder layer_directory = home_directory + "\\layer_files" rule_directory = aprx.homeFolder + "\\rule_packages" table_directory = home_directory + "\\tables" log_directory = aprx.homeFolder + "\\Logs" project_ws = aprx.defaultGeodatabase else: # debug input_features = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.3\3DToolsForPowerLines\Testing.gdb\testing_riverside' tower_height = "height" voltage = "400kV" do_sag_to_span = True conductor_name = "Sample Conductor 400" line_type = "Transmission" horizontal_tension = 4500 output_features = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.3\3DToolsForPowerLines\Testing.gdb\testing_riverside_3D' structure_type = "Lattice" circuits = 2 alignment = "Horizontal" insulator_hang_type = "Single" shield_wires = 0 tower_material = "Steel" endPoints = "None" #Both, Start, End, None home_directory = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.3\3DToolsForPowerLines' layer_directory = home_directory + "\\layer_files" rule_directory = home_directory + "\\rule_packages" table_directory = home_directory + "\\tables" log_directory = home_directory + "\\Logs" project_ws = home_directory + "\\Testing.gdb" scratch_ws = common_lib.create_gdb(home_directory, "Intermediate.gdb") arcpy.env.workspace = scratch_ws arcpy.env.overwriteOutput = True default_SagToSpanRatio = 0.035 # This number is used in the book. TODO make this user variable start_time = time.clock() in_memory = "in_memory" # check if input exists if arcpy.Exists(input_features): # test input type # current support 3D line only. TODO 2D line, 2D/3D points # set units input_z_unit = common_lib.get_z_unit(input_features, verbose) desc = arcpy.Describe(input_features) if desc.shapeType in ["Polyline", "Line", "Point"]: zValues = desc.hasZ if zValues: if desc.shapeType == "Point": # check for Line and Tower attribute line_attribute = "Line" tower_attribute = "Tower" if common_lib.check_fields( input_features, [line_attribute, tower_attribute], False, verbose) == 0: # process points lines_name = "lines_from_points" if in_memory_switch: arcpy.AddMessage( "Using in memory for processing") # junctions points needed for FFCER pointToLines = in_memory + "/" + lines_name else: # junctions points needed for makeSpans: FFCER generates 3D points with _Points in name pointToLines = os.path.join( scratch_ws, lines_name) arcpy.PointsToLine_management( input_features, pointToLines, line_attribute, tower_attribute) input_features = pointToLines else: arcpy.AddError("Input feature class requires a '" + line_attribute + "' and '" + tower_attribute + "' attribute. Exiting...") input_features = None if len(tower_height) > 0: if common_lib.check_fields(input_features, [tower_height], False, verbose) == 0: tower_attribute = "esri_tower_height" # create internal tower_height attribute if input_features: # make a copy to grab the selection input_source_copy = os.path.join( scratch_ws, "line_copy") if arcpy.Exists(input_source_copy): arcpy.Delete_management(input_source_copy) arcpy.CopyFeatures_management(input_features, input_source_copy) # create tower height attribute. set to zero for non tower height workflow # tower_attribute = "esri_tower_height" # common_lib.delete_add_field(input_source_copy, tower_attribute, "TEXT") # arcpy.CalculateField_management(input_source_copy, tower_attribute, 0, "PYTHON_9.3", None) # # # if user chooses an attribute, copy over. # if len(tower_height) > 0: # if common_lib.check_fields(input_source_copy, [tower_height], False, verbose) == 0: # # create internal tower_height attribute # common_lib.calculate_field_from_other_field(None, input_source_copy, tower_height, tower_attribute, "plus", 0, False, verbose) # check number of selected features num_features = int( arcpy.GetCount_management( input_source_copy).getOutput(0)) if num_features == 0: raise NoneSelected else: # check if conductor table exists... haveTables = False haveTower = False haveConductor = False inTowerTable = os.path.join( table_directory, TOWERTABLENAME) inConductorTable = os.path.join( table_directory, CONDUCTORTABLENAME) if arcpy.Exists(inTowerTable) and arcpy.Exists( inConductorTable): arcpy.AddMessage( "Reading tower and conductor tables: " + inTowerTable + ", " + inConductorTable + ".") inTowerSpreadsheet = inTowerTable + "\\" + TOWERINSHEET inConductorSpreadsheet = inConductorTable + "\\" + CONDUCTORINSHEET # table fields for Tower LU table. voltageField = "Voltage" minVField = "MinVSeparation" minHField = "MinHSeparation" minimumGroundClearanceField = "MinimumGroundClearance" beamColorField = "BeamColor" tableUnitsField = "Units" tower_field_list = [ voltageField, minVField, minHField, minimumGroundClearanceField, beamColorField, tableUnitsField ] # table fields for Conductor LU table. nameField = "ConductorName" weightField = "WeightPerUnitLength" rbsField = "RBS" conductor_field_list = [ nameField, weightField, rbsField, voltageField ] # read tower table code, tower_gdb_table = common_lib.import_table_with_required_fields( inTowerSpreadsheet, project_ws, TOWERTABLE, tower_field_list, verbose) if code == 0: haveTower = True else: msg_body = create_msg_body( "Failed to import " + inTowerSpreadsheet + "!", 0, 0) msg(msg_body, WARNING) haveTables = False # import conductor table code, conductor_gdb_table = common_lib.import_table_with_required_fields( inConductorSpreadsheet, project_ws, CONDUCTORTABLE, conductor_field_list, verbose) if code == 0: haveConductor = True else: msg_body = create_msg_body( "Failed to import " + inConductorSpreadsheet + "!", 0, 0) msg(msg_body, WARNING) haveTables = False if haveTower and haveConductor: haveTables = True pass else: msg_body = create_msg_body( "Failed to import necessary LUT tables!", 0, 0) msg(msg_body, ERROR) haveTables = False else: msg_body = create_msg_body( "Can't find: " + inTowerTable + " and/or " + inConductorTable + "!", 0, 0) msg(msg_body, WARNING) haveTables = False if haveTables: tower_configuration = create_3D_catenary_from_line.TowerConfiguration( ) # set parameters from UI tower_configuration.line_type = line_type tower_configuration.structure_type = structure_type tower_configuration.circuits = int(circuits) tower_configuration.alignment = alignment tower_configuration.shield_wires = int( shield_wires) tower_configuration.insulator_hang_type = insulator_hang_type tower_configuration.tower_material = tower_material msg_body = ("Retrieving values for " + voltage + " in " + TOWERTABLENAME) msg(msg_body) if do_sag_to_span == False: msg_body = ("Retrieving values for " + conductor_name + " in " + CONDUCTORTABLENAME) msg(msg_body) expression = """{} = '{}'""".format( arcpy.AddFieldDelimiters( tower_gdb_table, tower_field_list[0]), voltage) # read additional parameters from tower table with arcpy.da.SearchCursor( tower_gdb_table, tower_field_list, expression) as s_cursor: count = 0 for s_row in s_cursor: # read clearances and attachment height etc from TOWER table tower_configuration.voltage = "{0}".format( s_row[0]) tower_configuration.conductor_vertical_clearance = float( "{:.2f}".format(s_row[1])) tower_configuration.conductor_horizontal_clearance = float( "{:.2f}".format(s_row[2])) tower_configuration.minimum_ground_clearance = float( "{:.2f}".format(s_row[3])) tower_configuration.beam_color = "{0}".format( s_row[4]) tower_configuration.units = "{0}".format( s_row[5]) if do_sag_to_span is False and len( conductor_name) > 0: # read additional parameters from conductor table expression = """{} = '{}'""".format( arcpy.AddFieldDelimiters( conductor_gdb_table, conductor_field_list[0]), conductor_name) with arcpy.da.SearchCursor( conductor_gdb_table, conductor_field_list, expression) as s_cursor: count = 0 for s_row in s_cursor: # read clearances and attachment height etc from CONDUCTOR table line_weight = "{:.4f}".format( s_row[1]) sag_to_span_ratio = None arcpy.AddMessage( "Creating catenaries with a horizontal tension of: " + str(horizontal_tension) + " pounds and " + str(line_weight) + " pound weight per unit length.") else: if line_type == "Transmission": line_weight = 1.096 else: line_weight = 0.5 horizontal_tension = None sag_to_span_ratio = default_SagToSpanRatio arcpy.AddMessage( "Creating catenaries with a sagToSpan ratio of: " + str(sag_to_span_ratio) + " and " + str(line_weight) + " pound weight per unit length.") catenary, TowerModels, JunctionPoints, TowerPlacementPoints = create_3D_catenary_from_line.makeTowersAndJunctions( lc_scratch_ws=scratch_ws, lc_rule_dir=rule_directory, lc_input_features=input_features, lc_testLineWeight=float(line_weight), lc_sag_to_span_ratio=sag_to_span_ratio, lc_horizontal_tension=horizontal_tension, lc_tower_configuration=tower_configuration, lc_ends=endPoints, lc_output_features=output_features, lc_debug=verbose, lc_use_in_memory=in_memory_switch) if catenary and TowerModels and JunctionPoints and TowerPlacementPoints: if arcpy.Exists(catenary) and arcpy.Exists(TowerModels) and\ arcpy.Exists(TowerPlacementPoints) and arcpy.Exists(JunctionPoints): arcpy.SetParameter( 9, TowerPlacementPoints) arcpy.SetParameter(10, JunctionPoints) arcpy.SetParameter( 11, TowerModels ) # reordered these lines just for good chi. # create layer, set layer file # apply transparency here // checking if symbology layer is present z_unit = common_lib.get_z_unit( catenary, verbose) if z_unit == "Feet": if line_type == "Transmission": catenarySymbologyLayer = layer_directory + "\\transmission3Dfeet.lyrx" else: catenarySymbologyLayer = layer_directory + "\\distribution3Dfeet.lyrx" else: if line_type == "Transmission": catenarySymbologyLayer = layer_directory + "\\transmission3Dmeter.lyrx" else: catenarySymbologyLayer = layer_directory + "\\distribution3Dmeter.lyrx" output_layer4 = common_lib.get_name_from_feature_class( catenary) arcpy.MakeFeatureLayer_management( catenary, output_layer4) if arcpy.Exists( catenarySymbologyLayer): arcpy.ApplySymbologyFromLayer_management( output_layer4, catenarySymbologyLayer) else: msg_body = create_msg_body( "Can't find" + catenarySymbologyLayer + " in " + layer_directory, 0, 0) msg(msg_body, WARNING) if output_layer4: arcpy.SetParameter( 12, output_layer4) else: raise NoCatenaryOutput else: end_time = time.clock() msg_body = create_msg_body( "Can't find 3D catenaries or towers. Exiting...", start_time, end_time) msg(msg_body, WARNING) else: end_time = time.clock() msg_body = create_msg_body( "No 3D catenaries or towers created. Exiting...", start_time, end_time) msg(msg_body, WARNING) else: msg_body = create_msg_body( "Can't find necessary tables!", 0, 0) msg(msg_body, WARNING) else: msg_body = create_msg_body( "Error processing input features.", 0, 0) msg(msg_body, WARNING) else: end_time = time.clock() msg_body = create_msg_body( "Input feature class: " + input_features + " does not have Z values. Exiting...", start_time, end_time) msg(msg_body, WARNING) else: end_time = time.clock() msg_body = create_msg_body( "Only input feature type: Point, PolyLine supported currently. Exiting...", start_time, end_time) msg(msg_body, WARNING) arcpy.ClearWorkspaceCache_management() if DeleteIntermediateData: fcs = common_lib.listFcsInGDB(scratch_ws) msg_prefix = "Deleting intermediate data..." msg_body = common_lib.create_msg_body(msg_prefix, 0, 0) common_lib.msg(msg_body) for fc in fcs: arcpy.Delete_management(fc) else: end_time = time.clock() msg_body = create_msg_body( "Input: " + input_features + " not found. Exiting...", start_time, end_time) msg(msg_body, WARNING) # end main code except LicenseError3D: print("3D Analyst license is unavailable") arcpy.AddError("3D Analyst license is unavailable") except NoPointLayer: print("Can't find attachment points layer. Exiting...") arcpy.AddError("Can't find attachment points layer. Exiting...") except NoPointLayer: print( "None or more than 1 guide line selected. Please select only 1 guide line. Exiting..." ) arcpy.AddError( "None or more than 1 guide line selected. Please select only 1 guide line. Exiting..." ) except NoCatenaryLayer: print("Can't find Catenary layer. Exiting...") arcpy.AddError("Can't find Catenary layer. Exiting...") except NoCatenaryOutput: print("Can't create Catenary output. Exiting...") arcpy.AddError("Can't create Catenary output. Exiting...") except NoSwaySurfaceOutput: print("Can't find SwaySurface output. Exiting...") arcpy.AddError("Can't find SwaySurface. Exiting...") except NoGuideLinesLayer: print("Can't find GuideLines output. Exiting...") arcpy.AddError("Can't find GuideLines. Exiting...") except MoreThan1Selected: print( "More than 1 line selected. Please select 1 guide line only. Exiting..." ) arcpy.AddError( "More than 1 line selected. Please select 1 guide line only. Exiting..." ) except NoneSelected: print("No features found. Exiting...") arcpy.AddError("No features found. Exiting...") except NoGuideLinesOutput: print("Can't create GuideLines output. Exiting...") arcpy.AddError("Can't create GuideLines. Exiting...") except arcpy.ExecuteError: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("With error message: %s" % synerror, ERROR) msg("ArcPy Error Message: %s" % arcpy.GetMessages(2), ERROR) except FunctionError as f_e: messages = f_e.args[0] msg("Error in function: %s" % messages["function"], ERROR) msg("Error on %s" % messages["line"], ERROR) msg("Error in file name: %s" % messages["filename"], ERROR) msg("With error message: %s" % messages["synerror"], ERROR) msg("ArcPy Error Message: %s" % messages["arc"], ERROR) except: line, filename, synerror = trace() msg("Error on %s" % line, ERROR) msg("Error in file name: %s" % filename, ERROR) msg("with error message: %s" % synerror, ERROR) finally: arcpy.CheckInExtension("3D")