Ejemplo n.º 1
0
def main():
    try:
        # Get Attributes from User
        if debugging == 0:
            ## User input
            input_source2 = arcpy.GetParameter(0)
            adjust_all = arcpy.GetParameter(1)

            # 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_source2 = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.2.3\Transmission_Lines\Testing.gdb\test_adjust_line_feet1'
            adjust_all = False

            home_directory = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.2\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_source2):
            # find associated catenary
            catenary_full_path = common_lib.get_full_path_from_layer(
                input_source2)
            catenary_full_path = catenary_full_path.replace(
                "_LineGuides_", "_")

            if arcpy.Exists(catenary_full_path):
                # make a copy to grab the selection
                arcpy.AddMessage("Adjusting catenary: " + catenary_full_path)
                arcpy.AddMessage(
                    "Adjusting with selection of guide lines: " +
                    common_lib.get_name_from_feature_class(input_source2))

                input_source2_copy = os.path.join(scratch_ws,
                                                  "guide_lines_copy")
                if arcpy.Exists(input_source2_copy):
                    arcpy.Delete_management(input_source2_copy)

                msg_body = create_msg_body(
                    "Making copy of " +
                    common_lib.get_name_from_feature_class(input_source2) +
                    " in " + scratch_ws, 0, 0)
                msg(msg_body)

                arcpy.CopyFeatures_management(input_source2,
                                              input_source2_copy)

                # check number of selected features
                num_features = int(
                    arcpy.GetCount_management(input_source2_copy).getOutput(0))

                if num_features != 1:
                    raise MoreThan1Selected
                else:
                    catenary, guide_lines = adjust_3D_catenary.adjustSpans(
                        lc_scratch_ws=scratch_ws,
                        lc_catenary=catenary_full_path,
                        lc_guide_lines=input_source2,
                        lc_adjust_all=adjust_all,
                        lc_debug=verbose,
                        lc_use_in_memory=False)
                    end_time = time.clock()

                    if catenary and guide_lines:
                        if arcpy.Exists(catenary) and arcpy.Exists(
                                guide_lines):

                            # 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":
                                catenarySymbologyLayer = layer_directory + "\\catenary3Dfeet.lyrx"
                            else:
                                catenarySymbologyLayer = layer_directory + "\\catenary3Dmeter.lyrx"

                            output_layer1 = common_lib.get_name_from_feature_class(
                                catenary)
                            arcpy.MakeFeatureLayer_management(
                                catenary, output_layer1)

                            if arcpy.Exists(catenarySymbologyLayer):
                                arcpy.ApplySymbologyFromLayer_management(
                                    output_layer1, catenarySymbologyLayer)
                            else:
                                msg_body = create_msg_body(
                                    "Can't find" + catenarySymbologyLayer +
                                    " in " + layer_directory, 0, 0)
                                msg(msg_body, WARNING)

                            if z_unit == "Feet":
                                guidelinesSymbologyLayer = layer_directory + "\\guidelines3Dfeet.lyrx"
                            else:
                                guidelinesSymbologyLayer = layer_directory + "\\guidelines3Dmeter.lyrx"

                            output_layer2 = common_lib.get_name_from_feature_class(
                                guide_lines)

                            arcpy.MakeFeatureLayer_management(
                                guide_lines, output_layer2)

                            if arcpy.Exists(guidelinesSymbologyLayer):
                                arcpy.ApplySymbologyFromLayer_management(
                                    output_layer2, guidelinesSymbologyLayer)
                            else:
                                msg_body = create_msg_body(
                                    "Can't find" + guidelinesSymbologyLayer +
                                    " in " + layer_directory, 0, 0)
                                msg(msg_body, WARNING)

                            if output_layer1:
                                if z_unit == "Feet":
                                    arcpy.SetParameter(2, output_layer1)
                                else:
                                    arcpy.SetParameter(3, output_layer1)
                            else:
                                raise NoCatenaryOutput

                            if output_layer2:
                                if z_unit == "Feet":
                                    arcpy.SetParameter(
                                        4,
                                        common_lib.get_full_path_from_layer(
                                            output_layer2))
                                else:
                                    arcpy.SetParameter(5, output_layer2)
                            else:
                                raise NoGuideLinesOutput

                            end_time = time.clock()
                            msg_body = create_msg_body(
                                "create_3D_catenary_tbx completed successfully.",
                                start_time, end_time)
                            msg(msg_body)
                        else:
                            end_time = time.clock()
                            msg_body = create_msg_body(
                                "No catenary or guide_lines created. Exiting...",
                                start_time, end_time)
                            msg(msg_body, WARNING)
                    else:
                        end_time = time.clock()
                        msg_body = create_msg_body(
                            "No catenary or guide_lines created. Exiting...",
                            start_time, end_time)
                        msg(msg_body, WARNING)

                    arcpy.ClearWorkspaceCache_management()

                    # end main code

                    msg(msg_body)
            else:
                NoCatenaryLayer
        else:
            raise NoGuideLinesLayer

    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 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 calculate_height(lc_input_features, lc_ws, lc_tin_dir, lc_input_surface,
                     lc_output_features, lc_log_dir, lc_debug,
                     lc_memory_switch):

    try:
        # create dem
        desc = arcpy.Describe(lc_input_features)
        if desc.spatialReference.linearUnitName in ['Foot_US', 'Foot']:
            unit = 'Feet'
        else:
            unit = 'Meters'

        # Generate raster from lasd
        if arcpy.Exists(lc_input_features):
            if arcpy.Exists(lc_output_features):
                arcpy.Delete_management(lc_output_features)

            # make a copy
            bridge_polys = lc_output_features + "_height"

            if arcpy.Exists(bridge_polys):
                arcpy.Delete_management(bridge_polys)

            arcpy.CopyFeatures_management(lc_input_features, bridge_polys)

            # create string field for featureFID
            oidFieldName = arcpy.Describe(bridge_polys).oidFieldName
            common_lib.delete_add_field(bridge_polys, esri_featureID, "TEXT")
            arcpy.CalculateField_management(bridge_polys, esri_featureID,
                                            "!" + oidFieldName + "!",
                                            "PYTHON_9.3")

            msg_body = create_msg_body(
                "Calculating height above surface for: " +
                common_lib.get_name_from_feature_class(lc_input_features), 0,
                0)
            msg(msg_body)

            # create bridge tin
            out_tin = os.path.join(lc_tin_dir, "bridge_tin")
            if arcpy.Exists(out_tin):
                arcpy.Delete_management(out_tin)

            msg_body = create_msg_body(
                "Creating raster for: " +
                common_lib.get_name_from_feature_class(lc_input_features), 0,
                0)
            msg(msg_body)

            arcpy.CreateTin_3d(
                out_tin,
                arcpy.Describe(bridge_polys).spatialReference,
                "{} Shape.Z Hard_Clip <None>".format(bridge_polys), "DELAUNAY")

            # turn to raster
            if 0:
                bridge_raster = "in_memory/bridge_raster"
            else:
                bridge_raster = os.path.join(lc_ws, "bridge_raster")
                if arcpy.Exists(bridge_raster):
                    arcpy.Delete_management(bridge_raster)

            # use same cell size as input surface
            cell_size = arcpy.GetRasterProperties_management(
                lc_input_surface, "CELLSIZEX")[0]

            dataType = "FLOAT"
            method = "LINEAR"
            sampling = "CELLSIZE " + str(cell_size)
            zfactor = "1"

            arcpy.TinRaster_3d(out_tin, bridge_raster, dataType, method,
                               sampling, zfactor)

            add_minimum_height_above_water_surface(lc_ws, bridge_polys,
                                                   bridge_raster,
                                                   lc_input_surface,
                                                   lc_memory_switch)

            # create point file for labeling
            if lc_memory_switch:
                bridge_points = "in_memory/bridge_points"
            else:
                bridge_points = os.path.join(lc_ws, "bridge_points")
                if arcpy.Exists(bridge_points):
                    arcpy.Delete_management(bridge_points)

            arcpy.FeatureToPoint_management(bridge_polys, bridge_points,
                                            "INSIDE")

            bridge_points3D = lc_output_features + "_points_3D"
            if arcpy.Exists(bridge_points3D):
                arcpy.Delete_management(bridge_points3D)

            # create 3D point
            arcpy.FeatureTo3DByAttribute_3d(bridge_points, bridge_points3D,
                                            zmin_field)

            # add unit field
            common_lib.delete_add_field(bridge_points3D, esri_unit, "TEXT")

            expression = """{} IS NOT NULL""".format(
                arcpy.AddFieldDelimiters(bridge_points3D, has_field))

            # select all points with good elevation values
            local_layer = common_lib.get_name_from_feature_class(
                bridge_points3D) + "_lyr"
            select_lyr = arcpy.MakeFeatureLayer_management(
                bridge_points3D, local_layer).getOutput(0)
            arcpy.SelectLayerByAttribute_management(select_lyr,
                                                    "NEW_SELECTION",
                                                    expression, None)

            z_unit = common_lib.get_z_unit(bridge_points3D, lc_debug)

            if z_unit == "Meters":
                expression = "'m'"
            else:
                expression = "'ft'"

            arcpy.CalculateField_management(select_lyr, esri_unit, expression,
                                            "PYTHON_9.3")
            arcpy.SelectLayerByAttribute_management(select_lyr,
                                                    "CLEAR_SELECTION")

            common_lib.delete_fields(bridge_polys, [min_field, zmin_field])
            common_lib.delete_fields(bridge_points3D, [min_field, zmin_field])

            return bridge_polys, bridge_points3D
        else:
            msg_body = create_msg_body(
                "Couldn't find input feature class: " + str(lc_input_features),
                0, 0)
            msg(msg_body, WARNING)

            return None

    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]))
Ejemplo n.º 4
0
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 calculate_height(lc_input_features, lc_ws, lc_tin_dir, lc_input_surface,
                     lc_is_hand, lc_dem, lc_output_features, lc_log_dir,
                     lc_debug, lc_memory_switch):

    try:
        if arcpy.Exists(lc_input_features):
            if arcpy.Exists(lc_output_features):
                arcpy.Delete_management(lc_output_features)

            # make a copy
            bridge_polys = lc_output_features + "_height"

            if arcpy.Exists(bridge_polys):
                arcpy.Delete_management(bridge_polys)

            arcpy.CopyFeatures_management(lc_input_features, bridge_polys)

            # create string field for featureFID
            oidFieldName = arcpy.Describe(bridge_polys).oidFieldName
            common_lib.delete_add_field(bridge_polys, esri_featureID, "TEXT")
            arcpy.CalculateField_management(bridge_polys, esri_featureID,
                                            "!" + oidFieldName + "!",
                                            "PYTHON_9.3")

            msg_body = create_msg_body(
                "Calculating height above surface for: " +
                common_lib.get_name_from_feature_class(lc_input_features), 0,
                0)
            msg(msg_body)

            had_field = "height_dem"

            # if HAND raster
            if lc_is_hand:
                arcpy.AddMessage(
                    "Assuming input surface " +
                    common_lib.get_name_from_feature_class(lc_input_surface) +
                    " is a HAND raster.")
                arcpy.AddMessage(
                    "First adding height above DEM to " +
                    common_lib.get_name_from_feature_class(lc_input_features) +
                    ".")
                add_minimum_height_above_drainage(lc_ws, bridge_polys, lc_dem,
                                                  had_field, lc_memory_switch)

                arcpy.AddMessage(
                    "Now adding height above HAND raster " +
                    common_lib.get_name_from_feature_class(lc_input_features) +
                    ".")

                add_minimum_height_above_HAND(lc_ws, bridge_polys,
                                              lc_input_surface, had_field,
                                              lc_memory_switch)
            else:
                # if just DEM
                arcpy.AddMessage(
                    "Assuming input surface " +
                    common_lib.get_name_from_feature_class(lc_input_surface) +
                    " is a digital elevation model.")
                arcpy.AddMessage(
                    "Adding height above input surface to " +
                    common_lib.get_name_from_feature_class(lc_input_features) +
                    ".")
                add_minimum_height_above_drainage(lc_ws, bridge_polys,
                                                  lc_input_surface, had_field,
                                                  lc_memory_switch)

            # create point file for labeling
            if lc_memory_switch:
                bridge_points = "in_memory/bridge_points"
            else:
                bridge_points = os.path.join(lc_ws, "bridge_points")
                if arcpy.Exists(bridge_points):
                    arcpy.Delete_management(bridge_points)

            arcpy.FeatureToPoint_management(bridge_polys, bridge_points,
                                            "INSIDE")

            bridge_points3D = lc_output_features + "_points_3D"
            if arcpy.Exists(bridge_points3D):
                arcpy.Delete_management(bridge_points3D)

            # create 3D point
            arcpy.FeatureTo3DByAttribute_3d(bridge_points, bridge_points3D,
                                            zmin_field)

            # add unit field
            z_unit = common_lib.get_z_unit(bridge_points3D, lc_debug)

            if z_unit == "Meters":
                expression = "'m'"
            else:
                expression = "'ft'"

            common_lib.delete_add_field(bridge_points3D, esri_unit, "TEXT")
            arcpy.CalculateField_management(bridge_points3D, esri_unit,
                                            expression, "PYTHON_9.3")

            return bridge_polys, bridge_points3D
        else:
            msg_body = create_msg_body(
                "Couldn't find input feature class: " + str(lc_input_features),
                0, 0)
            msg(msg_body, WARNING)

            return None

    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]))
def main():
    try:
        # Get Attributes from User
        if debugging == 0:
            ## User input
            input_source = arcpy.GetParameter(0)
            line_weight = arcpy.GetParameterAsText(1)
            horizontal_tension = arcpy.GetParameterAsText(2)
            output_features = arcpy.GetParameterAsText(3)

            # 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\Seattle_Utility_Sample.gdb\Attachment_Points'
            line_weight = 1.096
            horizontal_tension = 4500
            output_features = r'D:\Gert\Work\Esri\Solutions\Utilities\Electric\work2.2.3\Transmission_Lines\Testing.gdb\catenary3D'

            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()

        default_SagToSpanRatio = 0.035  # This number is used in the book. TODO make this user variable
        sag_to_span_ratio = default_SagToSpanRatio

        # check if input exists
        if arcpy.Exists(input_source):
            # make a copy to grab the selection
            # make new feature classes of observer and target input fcs. This is because FFCER doesn't work with selections

            arcpy.AddMessage(
                "Processing input source: " +
                common_lib.get_name_from_feature_class(input_source))

            input_source_copy = os.path.join(scratch_ws,
                                             "attachment_points_copy")
            if arcpy.Exists(input_source_copy):
                arcpy.Delete_management(input_source_copy)

            msg_body = create_msg_body(
                "Making copy of " +
                common_lib.get_name_from_feature_class(input_source) + " in " +
                scratch_ws, 0, 0)
            msg(msg_body)

            arcpy.CopyFeatures_management(input_source, input_source_copy)
        else:
            raise NoPointLayer

        desc = arcpy.Describe(input_source)

        catenary, guide_lines = create_3D_catenary.makeSpans(
            lc_scratch_ws=scratch_ws,
            lc_inPoints=input_source_copy,
            lc_testLineWeight=float(line_weight),
            lc_sag_to_span_ratio=sag_to_span_ratio,
            lc_horizontal_tension=float(horizontal_tension),
            lc_output_features=output_features,
            lc_debug=verbose,
            lc_use_in_memory=False,
            lc_cleanup=True,
            lc_caller=TOOLNAME)

        end_time = time.clock()

        if catenary and guide_lines:
            if arcpy.Exists(catenary) and arcpy.Exists(guide_lines):

                # 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":
                    catenarySymbologyLayer = layer_directory + "\\catenary3Dfeet.lyrx"
                else:
                    catenarySymbologyLayer = layer_directory + "\\catenary3Dmeter.lyrx"

                output_layer1 = common_lib.get_name_from_feature_class(
                    catenary)
                arcpy.MakeFeatureLayer_management(catenary, output_layer1)

                if arcpy.Exists(catenarySymbologyLayer):
                    arcpy.ApplySymbologyFromLayer_management(
                        output_layer1, catenarySymbologyLayer)
                else:
                    msg_body = create_msg_body(
                        "Can't find" + catenarySymbologyLayer + " in " +
                        layer_directory, 0, 0)
                    msg(msg_body, WARNING)

                if z_unit == "Feet":
                    guidelinesSymbologyLayer = layer_directory + "\\guidelines3Dfeet.lyrx"
                else:
                    guidelinesSymbologyLayer = layer_directory + "\\guidelines3Dmeter.lyrx"

                output_layer2 = common_lib.get_name_from_feature_class(
                    guide_lines)
                arcpy.MakeFeatureLayer_management(guide_lines, output_layer2)

                if arcpy.Exists(guidelinesSymbologyLayer):
                    arcpy.ApplySymbologyFromLayer_management(
                        output_layer2, guidelinesSymbologyLayer)
                else:
                    msg_body = create_msg_body(
                        "Can't find" + guidelinesSymbologyLayer + " in " +
                        layer_directory, 0, 0)
                    msg(msg_body, WARNING)

                if output_layer1:
                    if z_unit == "Feet":
                        arcpy.SetParameter(4, output_layer1)
                    else:
                        arcpy.SetParameter(5, output_layer1)
                else:
                    raise NoCatenaryOutput

                if output_layer2:
                    if z_unit == "Feet":
                        arcpy.SetParameter(6, output_layer2)
                    else:
                        arcpy.SetParameter(7, output_layer2)
                else:
                    raise NoGuideLinesOutput

                end_time = time.clock()
                msg_body = create_msg_body(
                    "create_3D_catenary_tbx completed successfully.",
                    start_time, end_time)
                msg(msg_body)
            else:
                end_time = time.clock()
                msg_body = create_msg_body(
                    "No catenary or guide_lines created. Exiting...",
                    start_time, end_time)
                msg(msg_body, WARNING)
        else:
            end_time = time.clock()
            msg_body = create_msg_body(
                "No catenary or guide_lines created. Exiting...", start_time,
                end_time)
            msg(msg_body, WARNING)

        arcpy.ClearWorkspaceCache_management()

        # end main code

        msg(msg_body)

    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 NoCatenaryOutput:
        print("Can't create Catenary output. Exiting...")
        arcpy.AddError("Can't Catenary output. 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_source = arcpy.GetParameter(0)
            no_flood_value = arcpy.GetParameterAsText(1)
            baseline_elevation_raster = arcpy.GetParameter(2)
            baseline_elevation_value = arcpy.GetParameterAsText(3)
            smooth_factor = arcpy.GetParameter(4)
            output_features = arcpy.GetParameterAsText(5)

            # 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\3DFloodImpact\work2.3\3DFloodImpact\3DFloodImpact.gdb\slr_6_ProjectRaster'
            no_flood_value = "NoData"
            baseline_elevation_raster = r''
            baseline_elevation_value = "0"
            smooth_factor = 0
            output_features = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\3DFloodImpact.gdb\FloodPolys'

            home_directory = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact'
            layer_directory = home_directory + "\\layer_files"
            rule_directory = home_directory + "\\rule_packages"
            log_directory = home_directory + "\\Logs"
            project_ws = home_directory + "\\3DFloodImpact.gdb"

        scratch_ws = common_lib.create_gdb(home_directory, "Intermediate.gdb")
        arcpy.env.workspace = scratch_ws
        arcpy.env.overwriteOutput = True

        start_time = time.clock()

        if arcpy.CheckExtension("3D") == "Available":
            arcpy.CheckOutExtension("3D")

            # check if input exists
            if arcpy.Exists(input_source):
                full_path_source = common_lib.get_full_path_from_layer(input_source)
            else:
                raise NoRasterLayer

            # check if input exists
            if arcpy.Exists(baseline_elevation_raster):
                full_path_baseline_raster = common_lib.get_full_path_from_layer(baseline_elevation_raster)
            else:
                full_path_baseline_raster = None

            desc = arcpy.Describe(input_source)

            flood_polygons = create_3Dflood_level.flood_from_raster(input_source=full_path_source,
                                        input_type=desc.dataType,
                                        no_flood_value=no_flood_value,
                                        baseline_elevation_raster=full_path_baseline_raster,
                                        baseline_elevation_value=baseline_elevation_value,
                                        outward_buffer=0,
                                        output_polygons=output_features,
                                        smoothing=smooth_factor,
                                        debug=debugging)

            # create layer, set layer file
            # apply transparency here // checking if symbology layer is present
            z_unit = common_lib.get_z_unit(flood_polygons, verbose)

            if z_unit == "Feet":
                floodSymbologyLayer = layer_directory + "\\flood3Dfeet.lyrx"
            else:
                floodSymbologyLayer = layer_directory + "\\flood3Dmeter.lyrx"

            output_layer = common_lib.get_name_from_feature_class(flood_polygons)
            arcpy.MakeFeatureLayer_management(flood_polygons, output_layer)

            if arcpy.Exists(floodSymbologyLayer):
                arcpy.ApplySymbologyFromLayer_management(output_layer, floodSymbologyLayer)
            else:
                msg_body = create_msg_body("Can't find" + floodSymbologyLayer + " in " + layer_directory, 0, 0)
                msg(msg_body, WARNING)

            if output_layer:
                if z_unit == "Feet":
                    arcpy.SetParameter(6, output_layer)
                else:
                    arcpy.SetParameter(7, output_layer)
            else:
                raise NoOutput

            end_time = time.clock()
            msg_body = create_msg_body("create_3Dflood_level_tbx completed successfully.", start_time, end_time)

        else:
            raise LicenseError3D

        arcpy.ClearWorkspaceCache_management()

        # end main code

        msg(msg_body)

    except LicenseError3D:
        print("3D Analyst license is unavailable")
        arcpy.AddError("3D Analyst license is unavailable")

    except NoRasterLayer:
        print("Can't find Raster layer. Exiting...")
        arcpy.AddError("Can't find Raster layer. Exiting...")

    except NoOutput:
        print("Can't create output. Exiting...")
        arcpy.AddError("Can't create output. 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")
Ejemplo n.º 8
0
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")