Esempio n. 1
0
def adjustSpans(lc_scratch_ws, lc_catenary, lc_guide_lines, lc_adjust_all, lc_debug, lc_use_in_memory):
    try:
        # First, find the from and to points, and line number for this guide line.
        fieldList = ["FromTower", "ToTower", "LineNumber", "FromX", "FromY", "FromZ", "ToX", "ToY", "ToZ", "SagDistance", "WeightPerUnitLength"]
        fieldAccess = utils.FieldAccess(fieldList)

        # lc_guide_lines can be a layer. There is only 1 feature (selected)
        cursor = arcpy.da.SearchCursor(lc_guide_lines, fieldList)
        # Process selected guidelines.
        # XX Pretend for now that only one guideline is selected.
        index = 0
        for row in cursor:
            # only one guideline is selected.
            if index == 0:
                fieldAccess.setRow(row)
                lineNumber = fieldAccess.getValue("LineNumber")
                fromTower = fieldAccess.getValue("FromTower")
                toTower = fieldAccess.getValue("ToTower")
                fromX = fieldAccess.getValue("FromX")
                fromY = fieldAccess.getValue("FromY")
                fromZ = fieldAccess.getValue("FromZ")
                toX = fieldAccess.getValue("ToX")
                toY = fieldAccess.getValue("ToY")
                toZ = fieldAccess.getValue("ToZ")
                sagDistance = fieldAccess.getValue("SagDistance")
                weightPerUnitLength = fieldAccess.getValue("WeightPerUnitLength")
                fromPointXYZ = vg.Point(fromX, fromY, fromZ)
                toPointXYZ = vg.Point(toX, toY, toZ)
                # Change to attachment point objects.
                fromPoint = create_3D_catenary.AttachmentPoint(fromPointXYZ, lineNumber, fromTower)
                toPoint = create_3D_catenary.AttachmentPoint(toPointXYZ, lineNumber, toTower)

                p("Initial sagDistance on feature:", sagDistance)

                # sag distance is None because we need to calculate it from the lineGuide
                # horizontal tension is not supplied.
                adjustedSpan = create_3D_catenary.makeSpan(fromPoint, toPoint, lc_guide_lines, weightPerUnitLength, None, None, None)
                newSpanDistance = adjustedSpan.sagDistance
                p("new sagDistance on feature:", newSpanDistance)

        if cursor:
            del cursor

        if lc_adjust_all:
            # We have already created the span with a sag distance.
            # For simplicity, we'll throw out that span object and make all six using that sag.
            adjustedSpans = []
            fieldList = ["FromTower", "ToTower", "LineNumber", "FromX", "FromY", "FromZ", "ToX", "ToY", "ToZ"]
            fieldAccess = utils.FieldAccess(fieldList)
            whereClause = "FromTower = " + str(fromTower) + " and ToTower = " + str(toTower)

            p("sagDistance for all lines", newSpanDistance)

            # search in full feature class, not just selection
            i = 0
            cursor = arcpy.da.SearchCursor(common_lib.get_full_path_from_layer(lc_guide_lines), fieldList, whereClause)
            for row in cursor:
                fieldAccess.setRow(row)
                lineNumber = fieldAccess.getValue("LineNumber")
                fromTower = fieldAccess.getValue("FromTower")
                toTower = fieldAccess.getValue("ToTower")
                fromX = fieldAccess.getValue("FromX")
                fromY = fieldAccess.getValue("FromY")
                fromZ = fieldAccess.getValue("FromZ")
                toX = fieldAccess.getValue("ToX")
                toY = fieldAccess.getValue("ToY")
                toZ = fieldAccess.getValue("ToZ")
                fromPointXYZ = vg.Point(fromX, fromY, fromZ)
                toPointXYZ = vg.Point(toX, toY, toZ)
                # Change to attachment point objects.
                fromPoint = create_3D_catenary.AttachmentPoint(fromPointXYZ, lineNumber, fromTower)
                toPoint = create_3D_catenary.AttachmentPoint(toPointXYZ, lineNumber, toTower)

                p("newSpanDistance in loop", newSpanDistance)
                adjustedSpan = create_3D_catenary.makeSpan(fromPoint, toPoint, common_lib.get_full_path_from_layer(lc_guide_lines), weightPerUnitLength, newSpanDistance, None)
                adjustedSpans.append(adjustedSpan)

                i+=1
                # arcpy.AddMessage(str(i))

            doSpanRemoveAndInsert(lc_catenary, common_lib.get_full_path_from_layer(lc_guide_lines), adjustedSpans)
        else:
            doSpanRemoveAndInsert(lc_catenary, common_lib.get_full_path_from_layer(lc_guide_lines), [adjustedSpan])

        if lc_use_in_memory:
            arcpy.Delete_management("in_memory")

        if lc_debug == 0:
            fcs = common_lib.listFcsInGDB(lc_scratch_ws)

            msg_prefix = "Deleting intermediate data..."

            msg_body = common_lib.create_msg_body(msg_prefix, 0, 0)
            common_lib.msg(msg_body)

            for fc in fcs:
                arcpy.Delete_management(fc)

        arcpy.ClearWorkspaceCache_management()

        return lc_catenary, common_lib.get_full_path_from_layer(lc_guide_lines)

    except arcpy.ExecuteError:
        # Get the tool error messages
        msgs = arcpy.GetMessages(2)
        arcpy.AddError(msgs)
    except Exception:
        e = sys.exc_info()[1]
        arcpy.AddMessage("Unhandled exception: " + str(e.args[0]))
    pass
def main():
    try:
        # Get Attributes from User
        if debugging == 0:
            # User input
            input_las_dataset = arcpy.GetParameterAsText(0)
            class_code = arcpy.GetParameter(1)
            cell_size = arcpy.GetParameterAsText(2)
            minimum_bridge_area = arcpy.GetParameterAsText(3)
            extrapolate_surface = arcpy.GetParameter(4)
            output_features = arcpy.GetParameterAsText(5)

            # script variables
            aprx = arcpy.mp.ArcGISProject("CURRENT")
            home_directory = aprx.homeFolder
            project_ws = aprx.defaultGeodatabase
        else:
            input_las_dataset = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\testing.lasd'
            class_code = 13
            cell_size = str(0.5)
            minimum_bridge_area = str(20)
            extrapolate_surface = False
            output_features = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\Testing.gdb\bridges'

            home_directory = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact'
            project_ws = home_directory + "\\3DFloodImpact.gdb"

        if os.path.exists(home_directory + "\\p20"):  # it is a package
            home_directory = home_directory + "\\p20"

        arcpy.AddMessage("Project Home Directory is: " + home_directory)

        # set directories
        layer_directory = home_directory + "\\layer_files"
        log_directory = home_directory + "\\Logs"
        if not os.path.exists(log_directory):
            os.makedirs(log_directory)

        #  ensure numerical input is correct
        # fail safe for Europe's comma's
        cell_size = float(re.sub("[,.]", ".", cell_size))
        minimum_bridge_area = float(re.sub("[,.]", ".", minimum_bridge_area))

        # rename layer files (for packaging)
        if os.path.exists(layer_directory):
            common_lib.rename_file_extension(layer_directory, ".txt", ".lyrx")

        # Create folders and intermediate gdb, if needed
        scratch_ws = common_lib.create_gdb(home_directory, "Intermediate.gdb")
        arcpy.env.workspace = scratch_ws
        arcpy.env.overwriteOutput = True

        start_time = time.clock()

        # check if input exists
        if arcpy.Exists(input_las_dataset):

            # extract the elevation layers
            bridges = extract_bridges_from_las.extract(
                lc_lasd=input_las_dataset,
                lc_ws=scratch_ws,
                lc_class_code=class_code,
                lc_cell_size=float(cell_size),
                lc_min_bridge_area=float(minimum_bridge_area),
                lc_extrapolate=extrapolate_surface,
                lc_output_features=output_features,
                lc_log_dir=log_directory,
                lc_debug=verbose,
                lc_memory_switch=in_memory_switch)

            if bridges:
                if arcpy.Exists(bridges):
                    arcpy.AddMessage("Adding Bridges")

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

                    arcpy.SetParameter(6, output_layer1)

                    end_time = time.clock()
                    msg_body = create_msg_body(
                        "extract_bridges_from_las completed successfully.",
                        start_time, end_time)
                    msg(msg_body)
                else:
                    end_time = time.clock()
                    msg_body = create_msg_body(
                        "No bridge surfaces created. Exiting...", start_time,
                        end_time)
                    msg(msg_body, WARNING)
            else:
                end_time = time.clock()
                msg_body = create_msg_body(
                    "No bridge surfaces created. Exiting...", start_time,
                    end_time)
                msg(msg_body, WARNING)

            arcpy.ClearWorkspaceCache_management()

            if DeleteIntermediateData:
                fcs = common_lib.listFcsInGDB(scratch_ws)
                rs = common_lib.list_rasters_in_gdb(scratch_ws, verbose)

                msg_prefix = "Deleting intermediate data..."

                msg_body = common_lib.create_msg_body(msg_prefix, 0, 0)
                common_lib.msg(msg_body)

                for fc in fcs:
                    arcpy.Delete_management(fc)

                for r in rs:
                    arcpy.Delete_management(r)

            # end main code

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

    except NoPointLayer:
        print("Can't find attachment points layer. Exiting...")
        arcpy.AddError("Can't find attachment points layer. Exiting...")

    except NoCatenaryLayer:
        print("Can't find Catenary layer. Exiting...")
        arcpy.AddError("Can't find Catenary layer. Exiting...")

    except NoCatenaryOutput:
        print("Can't create Catenary output. Exiting...")
        arcpy.AddError("Can't create Catenary output. Exiting...")

    except NoSwaySurfaceOutput:
        print("Can't find SwaySurface output. Exiting...")
        arcpy.AddError("Can't find SwaySurface. Exiting...")

    except NoGuideLinesLayer:
        print("Can't find GuideLines output. Exiting...")
        arcpy.AddError("Can't find GuideLines. Exiting...")

    except MoreThan1Selected:
        print(
            "More than 1 line selected. Please select 1 guide line only. Exiting..."
        )
        arcpy.AddError(
            "More than 1 line selected. Please select 1 guide line only. Exiting..."
        )

    except NoGuideLinesOutput:
        print("Can't create GuideLines output. Exiting...")
        arcpy.AddError("Can't create GuideLines. Exiting...")

    except arcpy.ExecuteError:
        line, filename, synerror = trace()
        msg("Error on %s" % line, ERROR)
        msg("Error in file name:  %s" % filename, ERROR)
        msg("With error message:  %s" % synerror, ERROR)
        msg("ArcPy Error Message:  %s" % arcpy.GetMessages(2), ERROR)

    except FunctionError as f_e:
        messages = f_e.args[0]
        msg("Error in function:  %s" % messages["function"], ERROR)
        msg("Error on %s" % messages["line"], ERROR)
        msg("Error in file name:  %s" % messages["filename"], ERROR)
        msg("With error message:  %s" % messages["synerror"], ERROR)
        msg("ArcPy Error Message:  %s" % messages["arc"], ERROR)

    except:
        line, filename, synerror = trace()
        msg("Error on %s" % line, ERROR)
        msg("Error in file name:  %s" % filename, ERROR)
        msg("with error message:  %s" % synerror, ERROR)

    finally:
        arcpy.CheckInExtension("3D")
Esempio n. 3
0
def main():
    try:
        # Get Attributes from User
        if debugging == 0:
            # User input
            input_features = arcpy.GetParameterAsText(0)
            input_surface = arcpy.GetParameter(1)
            output_features = arcpy.GetParameterAsText(2)

            # script variables
            aprx = arcpy.mp.ArcGISProject("CURRENT")
            home_directory = aprx.homeFolder
            project_ws = aprx.defaultGeodatabase
            tin_directory = home_directory + "\TINs"
        else:
            input_features = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\Testing.gdb\bridges_test_surfaces'
            input_surface = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\ArcHydro\TSDepth\wse_28'
            output_features = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact\Testing.gdb\bridges_HAS'

            home_directory = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact'
            project_ws = home_directory + "\\3DFloodImpact.gdb"
            tin_directory = home_directory + "\TINs"

        if os.path.exists(home_directory + "\\p20"):  # it is a package
            home_directory = home_directory + "\\p20"
        if not os.path.exists(tin_directory):
            os.makedirs(tin_directory)

        arcpy.AddMessage("Project Home Directory is: " + home_directory)

        # set directories
        layer_directory = home_directory + "\\layer_files"
        log_directory = home_directory + "\\Logs"
        if not os.path.exists(log_directory):
            os.makedirs(log_directory)

        # rename layer files (for packaging)
        if os.path.exists(layer_directory):
            common_lib.rename_file_extension(layer_directory, ".txt", ".lyrx")

        # Create folders and intermediate gdb, if needed
        scratch_ws = common_lib.create_gdb(home_directory, "Intermediate.gdb")
        arcpy.env.workspace = scratch_ws
        arcpy.env.overwriteOutput = True

        start_time = time.clock()

        # check if input exists
        if arcpy.Exists(input_features):
            if arcpy.Exists(input_surface):

                z_values = arcpy.Describe(input_features).hasZ

                if z_values:
                    # extract the elevation layers
                    bridges, bridge_points = calculate_height_above_water_surface.calculate_height(
                        lc_input_features=input_features,
                        lc_ws=scratch_ws,
                        lc_tin_dir=tin_directory,
                        lc_input_surface=input_surface,
                        lc_output_features=output_features,
                        lc_log_dir=log_directory,
                        lc_debug=verbose,
                        lc_memory_switch=in_memory_switch)

                    if bridges and bridge_points:
                        # add symbology to points and add layer
                        output_layer1 = common_lib.get_name_from_feature_class(
                            bridges)
                        arcpy.MakeFeatureLayer_management(
                            bridges, output_layer1)

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

                        symbology_layer = layer_directory + "\\has_labels.lyrx"

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

                        arcpy.SetParameter(3, output_layer1)
                        arcpy.SetParameter(4, output_layer2)

                        end_time = time.clock()
                        msg_body = create_msg_body(
                            "calculate_height_above_water_surface completed successfully.",
                            start_time, end_time)
                        msg(msg_body)
                    else:
                        end_time = time.clock()
                        msg_body = create_msg_body(
                            "No bridge surfaces and points created. Exiting...",
                            start_time, end_time)
                        msg(msg_body, WARNING)

                    arcpy.ClearWorkspaceCache_management()

                    if DeleteIntermediateData:
                        fcs = common_lib.listFcsInGDB(scratch_ws)
                        rs = common_lib.list_rasters_in_gdb(
                            scratch_ws, verbose)

                        msg_prefix = "Deleting intermediate data..."

                        msg_body = common_lib.create_msg_body(msg_prefix, 0, 0)
                        common_lib.msg(msg_body)

                        for fc in fcs:
                            arcpy.Delete_management(fc)

                        for r in rs:
                            arcpy.Delete_management(r)
                else:
                    raise NoRaster
            else:
                raise No3DFeatures

            # end main code

    except No3DFeatures:
        # The input has no 3D features
        #
        print(
            '2D features are not supported. Make sure the input layer is a PolygonZ feature class.'
        )
        arcpy.AddError(
            '2D features are not supported. Make sure the input layer is a PolygonZ feature class.'
        )

    except NoRaster:
        # Can't find input raster
        #
        print("Can't find input raster.")
        arcpy.AddError("Can't find input raster.")

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

    except NoPointLayer:
        print("Can't find attachment points layer. Exiting...")
        arcpy.AddError("Can't find attachment points layer. Exiting...")

    except MoreThan1Selected:
        print(
            "More than 1 line selected. Please select 1 guide line only. Exiting..."
        )
        arcpy.AddError(
            "More than 1 line selected. Please select 1 guide line only. Exiting..."
        )

    except arcpy.ExecuteError:
        line, filename, synerror = trace()
        msg("Error on %s" % line, ERROR)
        msg("Error in file name:  %s" % filename, ERROR)
        msg("With error message:  %s" % synerror, ERROR)
        msg("ArcPy Error Message:  %s" % arcpy.GetMessages(2), ERROR)

    except FunctionError as f_e:
        messages = f_e.args[0]
        msg("Error in function:  %s" % messages["function"], ERROR)
        msg("Error on %s" % messages["line"], ERROR)
        msg("Error in file name:  %s" % messages["filename"], ERROR)
        msg("With error message:  %s" % messages["synerror"], ERROR)
        msg("ArcPy Error Message:  %s" % messages["arc"], ERROR)

    except:
        line, filename, synerror = trace()
        msg("Error on %s" % line, ERROR)
        msg("Error in file name:  %s" % filename, ERROR)
        msg("with error message:  %s" % synerror, ERROR)

    finally:
        arcpy.CheckInExtension("3D")
def flood_from_raster(input_source, input_type, no_flood_value,
                      baseline_elevation_raster, baseline_elevation_value,
                      outward_buffer, output_polygons, smoothing, debug):
    try:
        # Get Attributes from User
        if debug == 0:
            # script variables
            aprx = arcpy.mp.ArcGISProject("CURRENT")
            home_directory = aprx.homeFolder
            tiff_directory = home_directory + "\\Tiffs"
            tin_directory = home_directory + "\\Tins"
            scripts_directory = aprx.homeFolder + "\\Scripts"
            rule_directory = aprx.homeFolder + "\\rule_packages"
            log_directory = aprx.homeFolder + "\\Logs"
            layer_directory = home_directory + "\\layer_files"
            project_ws = aprx.defaultGeodatabase

            enableLogging = True
            DeleteIntermediateData = True
            verbose = 0
            use_in_memory = True
        else:
            # debug
            home_directory = r'D:\Gert\Work\Esri\Solutions\3DFloodImpact\work2.3\3DFloodImpact'
            tiff_directory = home_directory + "\\Tiffs"
            tin_directory = home_directory + "\\Tins"
            scripts_directory = home_directory + "\\Scripts"
            rule_directory = home_directory + "\\rule_packages"
            log_directory = home_directory + "\\Logs"
            layer_directory = home_directory + "\\layer_files"
            project_ws = home_directory + "\\Results.gdb"

            enableLogging = False
            DeleteIntermediateData = True
            verbose = 1
            use_in_memory = False

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

        # fail safe for Europese's comma's
        baseline_elevation_value = float(
            re.sub("[,.]", ".", baseline_elevation_value))

        if not os.path.exists(tiff_directory):
            os.makedirs(tiff_directory)

        if not os.path.exists(tin_directory):
            os.makedirs(tin_directory)

        common_lib.set_up_logging(log_directory, TOOLNAME)
        start_time = time.clock()

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

            if arcpy.CheckExtension("Spatial") == "Available":
                arcpy.CheckOutExtension("Spatial")

                flood_level_layer_mp = None

                desc = arcpy.Describe(input_source)

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

                spatial_ref = desc.spatialReference

                # create IsNull to be used to clip and check for NoData.
                if use_in_memory:
                    is_null0 = "in_memory/is_null0"
                else:
                    is_null0 = os.path.join(scratch_ws, "is_null0")
                    if arcpy.Exists(is_null0):
                        arcpy.Delete_management(is_null0)

                is_null_raster = arcpy.sa.IsNull(input_source)
                is_null_raster.save(is_null0)

                if spatial_ref.type == 'PROJECTED' or spatial_ref.type == 'Projected':
                    # check input source type: projected rasters ONLY!!!!
                    # check type, if polygon -> convert to raster
                    if input_type == "RasterLayer" or input_type == "RasterDataset" or input_type == "raster":
                        # prep raster
                        # smooth result using focal stats
                        if smoothing > 0:
                            if use_in_memory:
                                focal_raster = "in_memory/focal_raster"
                            else:
                                focal_raster = os.path.join(
                                    scratch_ws, "focal_raster")
                                if arcpy.Exists(focal_raster):
                                    arcpy.Delete_management(focal_raster)

                            if not (1 <= smoothing <= 100):
                                smoothing = 30

                            neighborhood = arcpy.sa.NbrRectangle(
                                smoothing, smoothing, "CELL")

                            flood_elev_raster = arcpy.sa.FocalStatistics(
                                input_source, neighborhood, "MEAN", "true")
                            flood_elev_raster.save(focal_raster)

                            # con
                            if use_in_memory:
                                smooth_input = "in_memory/smooth_input"
                            else:
                                smooth_input = os.path.join(
                                    scratch_ws, "smooth_input")
                                if arcpy.Exists(smooth_input):
                                    arcpy.Delete_management(smooth_input)

                            output = arcpy.sa.Con(is_null0, input_source,
                                                  flood_elev_raster)
                            output.save(smooth_input)

                            input_raster = smooth_input
                        else:
                            input_raster = input_source
                    else:
                        raise NotSupported

                    # use numeric value for determining non flooded areas: set these values to NoData. We need NoData for clippng later on
                    if no_flood_value != "NoData":
                        if common_lib.is_number(no_flood_value):
                            msg_body = create_msg_body(
                                "Setting no flood value: " + no_flood_value +
                                " to NoData in copy of " +
                                common_lib.get_name_from_feature_class(
                                    input_raster) + "...", 0, 0)
                            msg(msg_body)

                            if use_in_memory:
                                null_for_no_flooded_areas_raster = "in_memory/null_for_flooded"
                            else:
                                null_for_no_flooded_areas_raster = os.path.join(
                                    scratch_ws, "null_for_flooded")
                                if arcpy.Exists(
                                        null_for_no_flooded_areas_raster):
                                    arcpy.Delete_management(
                                        null_for_no_flooded_areas_raster)

                            whereClause = "VALUE = " + no_flood_value

                            # Execute SetNull
                            outSetNull_temp = arcpy.sa.SetNull(
                                input_raster, input_raster, whereClause)
                            outSetNull_temp.save(
                                null_for_no_flooded_areas_raster)

                            input_raster = null_for_no_flooded_areas_raster
                        else:
                            raise ValueError
                    else:
                        pass

                    msg_body = create_msg_body(
                        "Checking for NoData values in raster: " +
                        common_lib.get_name_from_feature_class(input_raster) +
                        ". NoData values are considered to be non-flooded areas!",
                        0, 0)
                    msg(msg_body)

                    max_value = arcpy.GetRasterProperties_management(
                        is_null0, "MAXIMUM")[0]
                    #                    has_nodata = arcpy.GetRasterProperties_management(input_raster, "ANYNODATA")[0] ## fails on some rasters

                    if int(max_value) == 1:
                        # 1. get the outline of the raster as polygon via RasterDomain
                        xy_unit = common_lib.get_xy_unit(input_raster, 0)

                        if xy_unit:
                            cell_size = arcpy.GetRasterProperties_management(
                                input_raster, "CELLSIZEX")

                            if baseline_elevation_raster:
                                # check celll size
                                cell_size_base = arcpy.GetRasterProperties_management(
                                    baseline_elevation_raster, "CELLSIZEX")

                                if cell_size_base.getOutput(
                                        0) == cell_size.getOutput(0):
                                    # Execute Plus
                                    if use_in_memory:
                                        flood_plus_base_raster = "in_memory/flooding_plus_base"
                                    else:
                                        flood_plus_base_raster = os.path.join(
                                            scratch_ws, "flooding_plus_base")
                                        if arcpy.Exists(
                                                flood_plus_base_raster):
                                            arcpy.Delete_management(
                                                flood_plus_base_raster)

                                    listRasters = []
                                    listRasters.append(input_raster)
                                    listRasters.append(
                                        baseline_elevation_raster)

                                    desc = arcpy.Describe(listRasters[0])
                                    arcpy.MosaicToNewRaster_management(
                                        listRasters, scratch_ws,
                                        "flooding_plus_base",
                                        desc.spatialReference, "32_BIT_FLOAT",
                                        cell_size, 1, "SUM", "")

                                    # check where there is IsNull and set the con values
                                    if use_in_memory:
                                        is_Null = "in_memory/is_Null"
                                    else:
                                        is_Null = os.path.join(
                                            scratch_ws, "is_Null")
                                        if arcpy.Exists(is_Null):
                                            arcpy.Delete_management(is_Null)

                                    is_Null_raster = arcpy.sa.IsNull(
                                        input_raster)
                                    is_Null_raster.save(is_Null)

                                    # Con
                                    if use_in_memory:
                                        flood_plus_base_raster_null = "in_memory/flooding_plus_base_null"
                                    else:
                                        flood_plus_base_raster_null = os.path.join(
                                            scratch_ws,
                                            "flooding_plus_base_null")
                                        if arcpy.Exists(
                                                flood_plus_base_raster_null):
                                            arcpy.Delete_management(
                                                flood_plus_base_raster_null)

                                    msg_body = create_msg_body(
                                        "Adding baseline elevation raster to input flood layer...",
                                        0, 0)
                                    msg(msg_body)

                                    fpbrn = arcpy.sa.Con(
                                        is_Null, input_raster,
                                        flood_plus_base_raster)
                                    fpbrn.save(flood_plus_base_raster_null)

                                    input_raster = flood_plus_base_raster_null
                                else:
                                    arcpy.AddWarning(
                                        "Cell size of " + input_raster +
                                        " is different than " +
                                        baseline_elevation_raster +
                                        ". Ignoring Base Elevation Raster.")
                            else:
                                if baseline_elevation_value > 0:
                                    if use_in_memory:
                                        flood_plus_base_raster = "in_memory/flood_plus_base"
                                    else:
                                        flood_plus_base_raster = os.path.join(
                                            scratch_ws, "flooding_plus_base")
                                        if arcpy.Exists(
                                                flood_plus_base_raster):
                                            arcpy.Delete_management(
                                                flood_plus_base_raster)
                                    arcpy.Plus_3d(input_raster,
                                                  baseline_elevation_value,
                                                  flood_plus_base_raster)

                                    input_raster = flood_plus_base_raster

                            msg_body = create_msg_body(
                                "Creating 3D polygons...", 0, 0)
                            msg(msg_body)

                            if use_in_memory:
                                raster_polygons = "in_memory/raster_polygons"
                            else:
                                raster_polygons = os.path.join(
                                    scratch_ws, "raster_polygons")
                                if arcpy.Exists(raster_polygons):
                                    arcpy.Delete_management(raster_polygons)

                            out_geom = "POLYGON"  # output geometry type
                            arcpy.RasterDomain_3d(input_raster,
                                                  raster_polygons, out_geom)

                            # 2. buffer it inwards so that we have a polygon only of the perimeter plus a few ???????cells inward???????.
                            if use_in_memory:
                                polygons_inward = "in_memory/inward_buffer"
                            else:
                                polygons_inward = os.path.join(
                                    scratch_ws, "inward_buffer")
                                if arcpy.Exists(polygons_inward):
                                    arcpy.Delete_management(polygons_inward)

                            x = float(
                                re.sub("[,.]", ".",
                                       str(cell_size.getOutput(0))))
                            #                            x = float(str(cell_size.getOutput(0)))

                            if x < 0.1:
                                arcpy.AddError(
                                    "Raster cell size is 0. Can't continue. Please check the raster properties."
                                )
                                raise ValueError
                            else:
                                buffer_in = 3 * int(x)

                                if xy_unit == "Feet":
                                    buffer_text = "-" + str(
                                        buffer_in) + " Feet"
                                else:
                                    buffer_text = "-" + str(
                                        buffer_in) + " Meters"

                                sideType = "OUTSIDE_ONLY"
                                arcpy.Buffer_analysis(raster_polygons,
                                                      polygons_inward,
                                                      buffer_text, sideType)

                                msg_body = create_msg_body(
                                    "Buffering flood edges...", 0, 0)
                                msg(msg_body)

                                # 3. mask in ExtractByMask: gives just boundary raster with a few cells inwards
                                if use_in_memory:
                                    extract_mask_raster = "in_memory/extract_mask"
                                else:
                                    extract_mask_raster = os.path.join(
                                        scratch_ws, "extract_mask")
                                    if arcpy.Exists(extract_mask_raster):
                                        arcpy.Delete_management(
                                            extract_mask_raster)

                                extract_temp_raster = arcpy.sa.ExtractByMask(
                                    input_raster, polygons_inward)
                                extract_temp_raster.save(extract_mask_raster)

                                # 4. convert the output to points
                                if use_in_memory:
                                    extract_mask_points = "in_memory/extract_points"
                                else:
                                    extract_mask_points = os.path.join(
                                        scratch_ws, "extract_points")
                                    if arcpy.Exists(extract_mask_points):
                                        arcpy.Delete_management(
                                            extract_mask_points)

                                arcpy.RasterToPoint_conversion(
                                    extract_mask_raster, extract_mask_points,
                                    "VALUE")

                                msg_body = create_msg_body(
                                    "Create flood points...", 0, 0)
                                msg(msg_body)

                                # 5. Interpolate: this will also interpolate outside the flood boundary which is
                                # what we need so we get a nice 3D poly that extends into the surrounding DEM
                                if use_in_memory:
                                    interpolated_raster = "in_memory/interpolate_raster"
                                else:
                                    interpolated_raster = os.path.join(
                                        scratch_ws, "interpolate_raster")
                                    if arcpy.Exists(interpolated_raster):
                                        arcpy.Delete_management(
                                            interpolated_raster)

                                zField = "grid_code"
                                power = 2
                                searchRadius = arcpy.sa.RadiusVariable(
                                    12, 150000)

                                msg_body = create_msg_body(
                                    "Interpolating flood points...", 0, 0)
                                msg(msg_body)

                                # Execute IDW
                                out_IDW = arcpy.sa.Idw(extract_mask_points,
                                                       zField, cell_size,
                                                       power)

                                # Save the output
                                out_IDW.save(interpolated_raster)

                                extent_poly = common_lib.get_extent_feature(
                                    scratch_ws, polygons_inward)

                                msg_body = create_msg_body(
                                    "Clipping terrain...", 0, 0)
                                msg(msg_body)

                                # clip the input surface
                                if use_in_memory:
                                    extent_clip_idwraster = "in_memory/extent_clip_idw"
                                else:
                                    extent_clip_idwraster = os.path.join(
                                        scratch_ws, "extent_clip_idw")
                                    if arcpy.Exists(extent_clip_idwraster):
                                        arcpy.Delete_management(
                                            extent_clip_idwraster)

                                # clip terrain to extent
                                arcpy.Clip_management(interpolated_raster, "#",
                                                      extent_clip_idwraster,
                                                      extent_poly)

                                # 6. clip the interpolated raster by (outward buffered) outline polygon
                                if use_in_memory:
                                    polygons_outward = "in_memory/outward_buffer"
                                else:
                                    polygons_outward = os.path.join(
                                        scratch_ws, "outward_buffer")
                                    if arcpy.Exists(polygons_outward):
                                        arcpy.Delete_management(
                                            polygons_outward)

                                outward_buffer += 0.5 * int(
                                    x
                                )  # we buffer out by half the raster cellsize

                                if outward_buffer > 0:
                                    if xy_unit == "Feet":
                                        buffer_text = str(
                                            outward_buffer) + " Feet"
                                    else:
                                        buffer_text = str(
                                            outward_buffer) + " Meters"

                                    sideType = "FULL"
                                    arcpy.Buffer_analysis(
                                        raster_polygons, polygons_outward,
                                        buffer_text, sideType)

                                    raster_polygons = polygons_outward

                                # clip the input surface
                                if use_in_memory:
                                    flood_clip_raster = "in_memory/flood_clip_raster"
                                else:
                                    flood_clip_raster = os.path.join(
                                        scratch_ws, "flood_clip_raster")
                                    if arcpy.Exists(flood_clip_raster):
                                        arcpy.Delete_management(
                                            flood_clip_raster)

                                msg_body = create_msg_body(
                                    "Clipping flood raster...", 0, 0)
                                msg(msg_body)

                                # clip terrain to extent
                                #                            arcpy.Clip_management(interpolated_raster, "#", flood_clip_raster, raster_polygons)    Check again
                                arcpy.Clip_management(interpolated_raster, "#",
                                                      flood_clip_raster,
                                                      raster_polygons)

                                # 7. Isnull, and Con to grab values from flood_clip_raster for
                                # create NUll mask
                                if use_in_memory:
                                    is_Null = "in_memory/is_Null"
                                else:
                                    is_Null = os.path.join(
                                        scratch_ws, "is_Null")
                                    if arcpy.Exists(is_Null):
                                        arcpy.Delete_management(is_Null)

                                is_Null_raster = arcpy.sa.IsNull(input_raster)
                                is_Null_raster.save(is_Null)

                                # Con
                                if use_in_memory:
                                    con_raster = "in_memory/con_raster"
                                else:
                                    con_raster = os.path.join(
                                        scratch_ws, "con_raster")
                                    if arcpy.Exists(con_raster):
                                        arcpy.Delete_management(con_raster)
                                temp_con_raster = arcpy.sa.Con(
                                    is_Null, interpolated_raster, input_raster)
                                temp_con_raster.save(con_raster)

                                msg_body = create_msg_body(
                                    "Merging rasters...", 0, 0)
                                msg(msg_body)

                                # 8. focal stats on raster to smooth?

                                # 9. copy raster to geotiff
                                if use_in_memory:
                                    con_raster_tif = "in_memory/con_raster_tif"
                                else:
                                    con_raster_tif = os.path.join(
                                        tiff_directory, "con_raster.tif")
                                    if arcpy.Exists(con_raster_tif):
                                        arcpy.Delete_management(con_raster_tif)

                                arcpy.CopyRaster_management(
                                    con_raster, con_raster_tif, "#", "#", "#",
                                    "#", "#", "32_BIT_FLOAT")

                                msg_body = create_msg_body(
                                    "Copying to tiff...", 0, 0)
                                msg(msg_body)

                                # 10. raster to TIN
                                zTol = 0.1
                                maxPts = 1500000
                                zFactor = 1
                                con_tin = os.path.join(tin_directory,
                                                       "con_tin")
                                if arcpy.Exists(con_tin):
                                    arcpy.Delete_management(con_tin)

                                # Execute RasterTin
                                arcpy.RasterTin_3d(con_raster_tif, con_tin,
                                                   zTol, maxPts, zFactor)

                                msg_body = create_msg_body(
                                    "Creating TIN...", 0, 0)
                                msg(msg_body)

                                # 11. TIN triangles
                                if use_in_memory:
                                    con_triangles = "in_memory/con_triangles"
                                else:
                                    con_triangles = os.path.join(
                                        scratch_ws, "con_triangles")
                                    if arcpy.Exists(con_triangles):
                                        arcpy.Delete_management(con_triangles)

                                arcpy.TinTriangle_3d(con_tin, con_triangles)

                                msg_body = create_msg_body(
                                    "Creating polygons...", 0, 0)
                                msg(msg_body)

                                # 12. make 2D polygons feature to feature class
                                arcpy.FeatureClassToFeatureClass_conversion(
                                    con_triangles, scratch_ws,
                                    "con_triangles_2D")

                                # 12. clip with smooth polygon
                                smooth_polygons = os.path.join(
                                    scratch_ws, "smooth_raster_polygons")
                                if arcpy.Exists(smooth_polygons):
                                    arcpy.Delete_management(smooth_polygons)

                                msg_body = create_msg_body(
                                    "Smoothing edges...", 0, 0)
                                msg(msg_body)

                                CA.SmoothPolygon(os.path.join(raster_polygons),
                                                 smooth_polygons, "PAEK", x,
                                                 "", "FLAG_ERRORS")

                                if use_in_memory:
                                    clip_smooth_triangles = "in_memory/clip_smooth_triangles"
                                else:
                                    clip_smooth_triangles = os.path.join(
                                        scratch_ws, "clip_smooth_triangles")
                                    if arcpy.Exists(clip_smooth_triangles):
                                        arcpy.Delete_management(
                                            clip_smooth_triangles)

                                msg_body = create_msg_body(
                                    "Clipping smooth edges...", 0, 0)
                                msg(msg_body)

                                # clip terrain to extent
                                arcpy.Clip_analysis(con_triangles,
                                                    smooth_polygons,
                                                    clip_smooth_triangles)

                                # clip to slightly lesser extent because of InterpolateShape fail.
                                area_extent = common_lib.get_extent_feature(
                                    scratch_ws, clip_smooth_triangles)

                                if use_in_memory:
                                    extent_inward = "in_memory/inward_extent_buffer"
                                else:
                                    extent_inward = os.path.join(
                                        scratch_ws, "inward_extent_buffer")
                                    if arcpy.Exists(extent_inward):
                                        arcpy.Delete_management(extent_inward)

                                buffer_in = 3

                                if xy_unit == "Feet":
                                    buffer_text = "-" + str(
                                        buffer_in) + " Feet"
                                else:
                                    buffer_text = "-" + str(
                                        buffer_in) + " Meters"

                                sideType = "FULL"
                                arcpy.Buffer_analysis(area_extent,
                                                      extent_inward,
                                                      buffer_text, sideType)

                                if use_in_memory:
                                    clip2_smooth_triangles = "in_memory/clip2_smooth_triangles"
                                else:
                                    clip2_smooth_triangles = os.path.join(
                                        scratch_ws, "clip2_smooth_triangles")
                                    if arcpy.Exists(clip2_smooth_triangles):
                                        arcpy.Delete_management(
                                            clip2_smooth_triangles)

                                msg_body = create_msg_body(
                                    "Clipping smooth edges a second time...",
                                    0, 0)
                                msg(msg_body)

                                # clip terrain to extent
                                arcpy.Clip_analysis(clip_smooth_triangles,
                                                    extent_inward,
                                                    clip2_smooth_triangles)

                                # 13. interpolate on TIN
                                if use_in_memory:
                                    clip_smooth_triangles3D = "in_memory/clip_smooth_traingles3D"
                                else:
                                    clip_smooth_triangles3D = os.path.join(
                                        scratch_ws, "clip_smooth_triangles3D")
                                    if arcpy.Exists(clip_smooth_triangles3D):
                                        arcpy.Delete_management(
                                            clip_smooth_triangles3D)

                                msg_body = create_msg_body(
                                    "Interpolating polygons on TIN", 0, 0)
                                msg(msg_body)
                                arcpy.InterpolateShape_3d(
                                    con_tin, clip2_smooth_triangles,
                                    clip_smooth_triangles3D, "#", 1, "LINEAR",
                                    "VERTICES_ONLY")

                                # 13. to multipatch
                                z_unit = common_lib.get_z_unit(
                                    clip_smooth_triangles3D, verbose)

                                # temp layer
                                flood_level_layer = "flood_level_layer"
                                arcpy.MakeFeatureLayer_management(
                                    clip_smooth_triangles3D, flood_level_layer)

                                # flood_level_mp = os.path.join(project_ws, common_lib.get_name_from_feature_class(input_raster) + "_3D")
                                flood_level_mp = output_polygons + "_3D"

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

                                arcpy.Layer3DToFeatureClass_3d(
                                    flood_level_layer, flood_level_mp)

                                # layer to be added to TOC
                                flood_level_layer_mp = common_lib.get_name_from_feature_class(
                                    flood_level_mp)
                                arcpy.MakeFeatureLayer_management(
                                    flood_level_mp, flood_level_layer_mp)

                                # apply transparency here // checking if symbology layer is present
                                if z_unit == "Feet":
                                    floodSymbologyLayer = layer_directory + "\\flood3Dfeet.lyrx"
                                else:
                                    floodSymbologyLayer = layer_directory + "\\flood3Dmeter.lyrx"

                                if not arcpy.Exists(floodSymbologyLayer):
                                    arcpy.AddWarning(
                                        "Can't find: " + floodSymbologyLayer +
                                        ". Symbolize features by error attribute to see data errors."
                                    )

                                arcpy.AddMessage("Results written to: " +
                                                 output_polygons)

                                if use_in_memory:
                                    arcpy.Delete_management("in_memory")

                                if DeleteIntermediateData:
                                    fcs = common_lib.listFcsInGDB(scratch_ws)

                                    msg_prefix = "Deleting intermediate data..."

                                    msg_body = common_lib.create_msg_body(
                                        msg_prefix, 0, 0)
                                    common_lib.msg(msg_body)

                                    for fc in fcs:
                                        arcpy.Delete_management(fc)

                                return flood_level_layer_mp

                            # 14. adjust 3D Z feet to meters???
                        else:
                            raise NoUnits
                    else:
                        raise NoNoDataError

                    end_time = time.clock()
                    msg_body = create_msg_body(
                        "Create 3D Flood Leveles completed successfully.",
                        start_time, end_time)
                else:
                    raise NotProjected
            else:
                raise LicenseErrorSpatial
        else:
            raise LicenseError3D

        arcpy.ClearWorkspaceCache_management()

        msg(msg_body)

    except NotProjected:
        print(
            "Input data needs to be in a projected coordinate system. Exiting..."
        )
        arcpy.AddError(
            "Input data needs to be in a projected coordinate system. Exiting..."
        )

    except NoLayerFile:
        print("Can't find Layer file. Exiting...")
        arcpy.AddError("Can't find Layer file. Exiting...")

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

    except LicenseErrorSpatial:
        print("Spatial Analyst license is unavailable")
        arcpy.AddError("Spatial Analyst license is unavailable")

    except NoNoDataError:
        print("Input raster does not have NODATA values")
        arcpy.AddError("Input raster does not have NODATA values")

    except NoUnits:
        print("No units detected on input data")
        arcpy.AddError("No units detected on input data")

    except NoPolygons:
        print("Input data can only be polygon features or raster datasets.")
        arcpy.AddError(
            "Input data can only be polygon features or raster datasets.")

    except ValueError:
        print("Input no flood value is not a number.")
        arcpy.AddError("Input no flood value is not a number.")

    except arcpy.ExecuteError:
        line, filename, synerror = trace()
        msg("Error on %s" % line, ERROR)
        msg("Error in file name:  %s" % filename, ERROR)
        msg("With error message:  %s" % synerror, ERROR)
        msg("ArcPy Error Message:  %s" % arcpy.GetMessages(2), ERROR)

    except FunctionError as f_e:
        messages = f_e.args[0]
        msg("Error in function:  %s" % messages["function"], ERROR)
        msg("Error on %s" % messages["line"], ERROR)
        msg("Error in file name:  %s" % messages["filename"], ERROR)
        msg("With error message:  %s" % messages["synerror"], ERROR)
        msg("ArcPy Error Message:  %s" % messages["arc"], ERROR)

    except:
        line, filename, synerror = trace()
        msg("Error on %s" % line, ERROR)
        msg("Error in file name:  %s" % filename, ERROR)
        msg("with error message:  %s" % synerror, ERROR)

    finally:
        arcpy.CheckInExtension("3D")
        arcpy.CheckInExtension("Spatial")
Esempio n. 5
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")
Esempio n. 6
0
def makeSpans(lc_scratch_ws, lc_inPoints, lc_testLineWeight, lc_sag_to_span_ratio, lc_horizontal_tension, lc_output_features, lc_debug, lc_use_in_memory, lc_cleanup, lc_caller):
    try:
        geometry_type = "POLYLINE"
        has_m = "DISABLED"
        has_z = "ENABLED"
        from_tower_field = "FromTower"
        to_tower_field = "ToTower"
        line_number_field = "LineNumber"
        count_field = "COUNT"

        from_X_field = "FromX"
        from_Y_field = "FromY"
        from_Z_field = "FromZ"
        To_X_field = "ToX"
        To_Y_field = "ToY"
        To_Z_field = "ToZ"
        sag_distance = "SagDistance"
        horizontal_tension = "HorizontalTension"
        line_lenght = "LineLength"
        weight_per_unit_length = "WeightPerUnitLength"

        transmission_line_name = "TransmissionLines3D"
        transmission_guide_name = "TransmissionLineGuide"
        in_memory = "in_memory"

        spatial_reference = arcpy.Describe(lc_inPoints).spatialReference

        # create empty feature class with required fields

#        msg_body = create_msg_body("Preparing output feature classes...", 0, 0)
#        msg(msg_body)

        if lc_use_in_memory:
            arcpy.AddMessage("Using in memory for processing")
            includedTransmissionLinesFC = in_memory + "/" + transmission_line_name

            arcpy.CreateFeatureclass_management(in_memory, transmission_line_name, geometry_type, "", has_m, has_z, spatial_reference)
        else:
            includedTransmissionLinesFC = lc_output_features + "_3D"

            includedTransmissionLinesFC_dirname = os.path.dirname(includedTransmissionLinesFC)
            includedTransmissionLinesFC_basename = os.path.basename(includedTransmissionLinesFC)

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

            arcpy.CreateFeatureclass_management(includedTransmissionLinesFC_dirname, includedTransmissionLinesFC_basename, geometry_type, "", has_m, has_z,
                                                    spatial_reference)

        fields1_dict = {from_tower_field:"LONG",
                            to_tower_field:"LONG",
                            line_number_field:"LONG",
                            count_field:"LONG",
                            sag_distance:"DOUBLE",
                            horizontal_tension:"DOUBLE",
                            line_lenght:"DOUBLE",
                            weight_per_unit_length:"DOUBLE"
                        }

        listoffields1 = []
        for k, v in fields1_dict.items():
            field = []
            field.append(k)
            field.append(v)
            listoffields1.append(field)

        arcpy.management.AddFields(includedTransmissionLinesFC, listoffields1)

#        common_lib.delete_add_field(includedTransmissionLinesFC, from_tower_field, "LONG")
#        common_lib.delete_add_field(includedTransmissionLinesFC, to_tower_field, "LONG")
#        common_lib.delete_add_field(includedTransmissionLinesFC, line_number_field, "LONG")
#        common_lib.delete_add_field(includedTransmissionLinesFC, count_field, "LONG")
#        common_lib.delete_add_field(includedTransmissionLinesFC, sag_distance, "DOUBLE")
#        common_lib.delete_add_field(includedTransmissionLinesFC, horizontal_tension, "DOUBLE")
#        common_lib.delete_add_field(includedTransmissionLinesFC, line_lenght, "DOUBLE")
#        common_lib.delete_add_field(includedTransmissionLinesFC, weight_per_unit_length, "DOUBLE")

        if lc_caller == "Create3Dcatenaryfromline":
            create_guidelines = False
        else:
            create_guidelines = True

        if create_guidelines:
            if lc_use_in_memory:
                includedTransmissionLineGuides = in_memory + "/" + transmission_guide_name

                arcpy.CreateFeatureclass_management(in_memory, transmission_guide_name, geometry_type, "", has_m, has_z, spatial_reference)
            else:
                includedTransmissionLineGuides = lc_output_features + "_LineGuides_3D"

                includedTransmissionLinesGuides_dirname = os.path.dirname(includedTransmissionLineGuides)
                includedTransmissionLinesGuides_basename = os.path.basename(includedTransmissionLineGuides)

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

                arcpy.CreateFeatureclass_management(includedTransmissionLinesGuides_dirname, includedTransmissionLinesGuides_basename, geometry_type, "", has_m, has_z,
                                                    spatial_reference)

            fields2_dict = {from_tower_field: "LONG",
                                to_tower_field: "LONG",
                                line_number_field: "LONG",
                                from_X_field: "DOUBLE",
                                from_Y_field: "DOUBLE",
                                from_Z_field: "DOUBLE",
                                To_X_field: "DOUBLE",
                                To_Y_field: "DOUBLE",
                                To_Z_field: "DOUBLE",
                                count_field: "LONG",
                                sag_distance: "DOUBLE",
                                weight_per_unit_length: "DOUBLE"
                            }

            listoffields2 = []
            for k, v in fields2_dict.items():
                field = []
                field.append(k)
                field.append(v)
                listoffields2.append(field)

            arcpy.management.AddFields(includedTransmissionLineGuides, listoffields2)

#            common_lib.delete_add_field(includedTransmissionLineGuides, from_tower_field, "LONG")
#            common_lib.delete_add_field(includedTransmissionLineGuides, to_tower_field, "LONG")
#            common_lib.delete_add_field(includedTransmissionLineGuides, line_number_field, "LONG")
#            common_lib.delete_add_field(includedTransmissionLineGuides, from_X_field, "DOUBLE")
#            common_lib.delete_add_field(includedTransmissionLineGuides, from_Y_field, "DOUBLE")
#            common_lib.delete_add_field(includedTransmissionLineGuides, from_Z_field, "DOUBLE")
#            common_lib.delete_add_field(includedTransmissionLineGuides, To_X_field, "DOUBLE")
#            common_lib.delete_add_field(includedTransmissionLineGuides, To_Y_field, "DOUBLE")
#            common_lib.delete_add_field(includedTransmissionLineGuides, To_Z_field, "DOUBLE")
#            common_lib.delete_add_field(includedTransmissionLineGuides, sag_distance, "DOUBLE")
#            common_lib.delete_add_field(includedTransmissionLineGuides, weight_per_unit_length, "DOUBLE")
        else:
            includedTransmissionLineGuides = None

        ############################################################################################### Chris continues...................
        attachmentPointList = []

        fieldList = ["SHAPE@X", "SHAPE@Y", "SHAPE@Z", "Line", "Tower"]
        fieldAccess = utils.FieldAccess(fieldList)
        cursor = arcpy.da.SearchCursor(lc_inPoints, fieldList)
        for row in cursor:
            fieldAccess.setRow(row)
            x = fieldAccess.getValue("SHAPE@X")
            y = fieldAccess.getValue("SHAPE@Y")
            z = fieldAccess.getValue("SHAPE@Z")
            lineNumber = fieldAccess.getValue("Line")
            towerNumber = fieldAccess.getValue("Tower")
            point = vg.Point(x, y, z)
            attachmentPoint = AttachmentPoint(point, lineNumber, towerNumber)
            attachmentPointList.append(attachmentPoint)
        if cursor:
            del cursor

        # Organize points into lists per line.
        dictionaryOfListsOfAttachmentPointsPerLine = {}
        for attachmentPoint in attachmentPointList:
            lineNumber = attachmentPoint.lineNumber
            if lineNumber in dictionaryOfListsOfAttachmentPointsPerLine.keys():
                listOfAttachmentPointsPerLine = dictionaryOfListsOfAttachmentPointsPerLine[lineNumber]
            else:
                listOfAttachmentPointsPerLine = []
                dictionaryOfListsOfAttachmentPointsPerLine[lineNumber] = listOfAttachmentPointsPerLine
            listOfAttachmentPointsPerLine.append(attachmentPoint)

        # Sort attachment points in each line list.
        # And make a list of line numbers for use in another dictionary.
        dictionaryOfSpanListsPerLine = {}
        lineNumberList = []
        for lineNumber in dictionaryOfListsOfAttachmentPointsPerLine.keys():
            lineNumberList.append(lineNumber)
            listOfAttachmentPointsPerLine = dictionaryOfListsOfAttachmentPointsPerLine[lineNumber]
            listOfAttachmentPointsPerLineSorted = sorted(listOfAttachmentPointsPerLine, key=lambda attachmentPoint: attachmentPoint.towerNumber)
            spanListPerThisLine = []
            for index in range(0, len(listOfAttachmentPointsPerLineSorted) - 1):
                fromPoint = listOfAttachmentPointsPerLineSorted[index]
                toPoint = listOfAttachmentPointsPerLineSorted[index + 1]

                # This is to give shield wires less sag, but only works when using the Easy Way.
                sagToSpanRatioForMakeSpan = None
                if lc_sag_to_span_ratio is not None:
                    sagToSpanRatioForMakeSpan = lc_sag_to_span_ratio
                    if lineNumber < 0:
                        sagToSpanRatioForMakeSpan = sagToSpanRatioForMakeSpan * 0.5

                span = makeSpan(fromPoint, toPoint, includedTransmissionLineGuides, lc_testLineWeight, sagToSpanRatio=sagToSpanRatioForMakeSpan,sagDistance=None, horizontalTension=lc_horizontal_tension)
                spanListPerThisLine.append(span)
            dictionaryOfSpanListsPerLine[lineNumber] = spanListPerThisLine

#        msg_body = create_msg_body("Writing all span lines to " + includedTransmissionLinesFC_basename + ".", 0, 0)
#        msg(msg_body)

        for index in range(0,len(lineNumberList)):
            lineNumber = lineNumberList[index]
            spanListPerThisLine = dictionaryOfSpanListsPerLine[lineNumber]
            # not TODO: CW, yes is has to run: switch is driven by includedTransmissionLineGuides inside the function.
            doInsertSpanAndGuideLine(includedTransmissionLinesFC, includedTransmissionLineGuides, spanListPerThisLine)

        if includedTransmissionLineGuides is not None:  # not TODO: CW, nope: see inside doInsertSpanAndGuideLine but could be coded more elegantly
            msg_body = create_msg_body(
                "Created helper Guide Lines feature class " + common_lib.get_name_from_feature_class(includedTransmissionLineGuides) + ".", 0, 0)
            msg(msg_body)

        # TODO check when necessary. When called from create_3D_catenary_from_line, this should not be called.

        if lc_cleanup:
            if lc_use_in_memory:
                arcpy.Delete_management("in_memory")

            if lc_debug == 0:
                fcs = common_lib.listFcsInGDB(lc_scratch_ws)

                msg_prefix = "Deleting intermediate data..."

                msg_body = common_lib.create_msg_body(msg_prefix, 0, 0)
                common_lib.msg(msg_body)

                for fc in fcs:
                    arcpy.Delete_management(fc)

            arcpy.ClearWorkspaceCache_management()

        return includedTransmissionLinesFC, includedTransmissionLineGuides

    except arcpy.ExecuteError:
        # Get the tool error messages
        msgs = arcpy.GetMessages(2)
        arcpy.AddError(msgs)
    except Exception:
        e = sys.exc_info()[1]
        arcpy.AddMessage("Unhandled exception: " + str(e.args[0]))
    pass
Esempio n. 7
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")