def integrated_width(fcInLines, fcInPolygons, fcOutLines, strMetricName="", boolSegmentPolygon=False, temp_workspace="in_memory"): fcMemLines = gis_tools.newGISDataset(temp_workspace, "lineNetwork") arcpy.CopyFeatures_management(fcInLines, fcMemLines) fieldLength = gis_tools.resetField(fcMemLines, "IW_Length", "DOUBLE") arcpy.CalculateField_management(fcMemLines, fieldLength, "!Shape!.length", "PYTHON") fcMemPolygons = gis_tools.newGISDataset(temp_workspace, 'Polygons') if boolSegmentPolygon: DividePolygonBySegment.main(fcMemLines, fcInPolygons, fcMemPolygons, temp_workspace, dblPointDensity=5.0) else: arcpy.CopyFeatures_management(fcInPolygons, fcMemPolygons) fieldPolygonArea = gis_tools.resetField(fcMemPolygons, strMetricName[0:6] + "Area", "DOUBLE") arcpy.CalculateField_management(fcMemPolygons, fieldPolygonArea, "!Shape!.area", "PYTHON") f_mappings = arcpy.FieldMappings() f_mappings.addTable(fcMemLines) fmap_area = arcpy.FieldMap() fmap_area.addInputField(fcMemPolygons, fieldPolygonArea) f_mappings.addFieldMap(fmap_area) arcpy.SpatialJoin_analysis(fcMemLines, fcMemPolygons, fcOutLines, "JOIN_ONE_TO_ONE", "KEEP_ALL", field_mapping=f_mappings, match_option="WITHIN") fieldIntegratedWidth = gis_tools.resetField(fcOutLines, "IW" + strMetricName[0:8], "DOUBLE") exp = "!" + fieldPolygonArea + r"! / !" + fieldLength + "!" print exp arcpy.CalculateField_management(fcOutLines, fieldIntegratedWidth, exp, "PYTHON_9.3") return fieldIntegratedWidth
def main(fcLineNetwork, fieldStreamRouteID, fieldConfinement, fieldConstriction, strSeedDistance, inputliststrWindowSize, outputWorkspace, tempWorkspace=arcpy.env.scratchWorkspace): """Perform a Moving Window Analysis on a Line Network.""" liststrWindowSize = inputliststrWindowSize.split(";") fcLineNetworkDissolved = gis_tools.newGISDataset( tempWorkspace, "GNAT_MWA_LineNetworkDissolved") arcpy.Dissolve_management(fcLineNetwork, fcLineNetworkDissolved, fieldStreamRouteID, multi_part=False, unsplit_lines=True) listLineGeometries = arcpy.CopyFeatures_management(fcLineNetworkDissolved, arcpy.Geometry()) listWindows = [] listSeeds = [] listWindowEvents = [] listgWindows = [] intSeedID = 0 iRoutes = int( arcpy.GetCount_management(fcLineNetworkDissolved).getOutput(0)) arcpy.SetProgressor("step", "Processing Each Route", 0, iRoutes, 1) iRoute = 0 with arcpy.da.SearchCursor( fcLineNetworkDissolved, ["SHAPE@", fieldStreamRouteID, "SHAPE@LENGTH"]) as scLines: for fLine in scLines: #Loop Through Routes arcpy.SetProgressorLabel("Route: " + str(iRoute) + " Seed Point: " + str(intSeedID)) arcpy.SetProgressorPosition(iRoute) gLine = fLine[0] dblSeedPointPosition = float( max(liststrWindowSize )) / 2 #Start Seeds at position of largest window while dblSeedPointPosition + float( max(liststrWindowSize)) / 2 < fLine[2]: arcpy.SetProgressorLabel("Route: " + str(iRoute) + " Seed Point: " + str(intSeedID)) gSeedPointPosition = gLine.positionAlongLine( dblSeedPointPosition) listSeeds.append([ scLines[1], intSeedID, gSeedPointPosition ]) #gSeedPointPosition.X,gSeedPointPosition.Y]) for strWindowSize in liststrWindowSize: dblWindowSize = float(strWindowSize) dblLengthStart = dblSeedPointPosition - dblWindowSize / 2 dblLengthEnd = dblSeedPointPosition + dblWindowSize / 2 gPointStartLocation = gLine.positionAlongLine( dblLengthStart) gPointEndLocation = gLine.positionAlongLine(dblLengthEnd) gTemp = arcpy.Geometry() listgWindowTemp = arcpy.SplitLineAtPoint_management( gLine, [gPointStartLocation, gPointEndLocation], gTemp, "1 METER") #TODO: Need a better method to select the line here!! for gWindowTemp in listgWindowTemp: if abs(gWindowTemp.length - dblWindowSize) < 10: listgWindows.append([ scLines[1], intSeedID, dblWindowSize, gWindowTemp ]) # End TODO listWindows.append([ scLines[1], intSeedID, dblWindowSize, gPointStartLocation ]) listWindows.append([ scLines[1], intSeedID, dblWindowSize, gPointEndLocation ]) listWindowEvents.append([ scLines[1], intSeedID, dblWindowSize, dblLengthStart, dblLengthEnd ]) dblSeedPointPosition = dblSeedPointPosition + float( strSeedDistance) intSeedID = intSeedID + 1 iRoute = iRoute + 1 fcSeedPoints = gis_tools.newGISDataset(tempWorkspace, "GNAT_MWA_SeedPoints") fcWindowEndPoints = gis_tools.newGISDataset(tempWorkspace, "GNAT_MWA_WindowEndPoints") fcWindowLines = gis_tools.newGISDataset(tempWorkspace, "GNAT_MWA_WindowLines") arcpy.CreateFeatureclass_management(tempWorkspace, "GNAT_MWA_SeedPoints", "POINT", spatial_reference=fcLineNetwork) arcpy.CreateFeatureclass_management(tempWorkspace, "GNAT_MWA_WindowEndPoints", "POINT", spatial_reference=fcLineNetwork) arcpy.CreateFeatureclass_management(tempWorkspace, "GNAT_MWA_WindowLines", "POLYLINE", spatial_reference=fcLineNetwork) gis_tools.resetField(fcSeedPoints, "RouteID", "LONG") gis_tools.resetField(fcSeedPoints, "SeedID", "LONG") gis_tools.resetField(fcWindowEndPoints, "RouteID", "LONG") gis_tools.resetField(fcWindowEndPoints, "SeedID", "LONG") gis_tools.resetField(fcWindowEndPoints, "Seg", "DOUBLE") gis_tools.resetField(fcWindowLines, "RouteID", "LONG") gis_tools.resetField(fcWindowLines, "SeedID", "LONG") gis_tools.resetField(fcWindowLines, "Seg", "DOUBLE") with arcpy.da.InsertCursor( fcSeedPoints, ["RouteID", "SeedID", "SHAPE@XY"]) as icSeedPoints: for row in listSeeds: icSeedPoints.insertRow(row) with arcpy.da.InsertCursor( fcWindowEndPoints, ["RouteID", "SeedID", "Seg", "SHAPE@XY"]) as icWindowEndPoints: for row in listWindows: icWindowEndPoints.insertRow(row) with arcpy.da.InsertCursor( fcWindowLines, ["RouteID", "SeedID", "Seg", "SHAPE@"]) as icWindowLines: for row in listgWindows: icWindowLines.insertRow(row) fcIntersected = gis_tools.newGISDataset( tempWorkspace, "GNAT_MWA_IntersectWindowAttributes") arcpy.Intersect_analysis([fcWindowLines, fcLineNetwork], fcIntersected, "ALL", output_type="LINE") # Confinement tblSummaryStatisticsConfinement = gis_tools.newGISDataset( tempWorkspace, "GNAT_MWA_SummaryStatsTableConfinement") arcpy.Statistics_analysis( fcIntersected, tblSummaryStatisticsConfinement, "Shape_Length SUM", fieldStreamRouteID + ";SeedID;Seg;" + fieldConfinement) tblSummaryStatisticsPivot = gis_tools.newGISDataset( tempWorkspace, "GNAT_MWA_SummaryStatisticsPivotTable") arcpy.PivotTable_management(tblSummaryStatisticsConfinement, "Route;SeedID;Seg", fieldConfinement, "SUM_Shape_Length", tblSummaryStatisticsPivot) fieldConfinementValue = gis_tools.resetField(tblSummaryStatisticsPivot, "CONF_Value", "DOUBLE") if len(arcpy.ListFields(tblSummaryStatisticsPivot, fieldConfinement + "1")) == 0: arcpy.AddField_management(tblSummaryStatisticsPivot, fieldConfinement + "1", "DOUBLE") if len(arcpy.ListFields(tblSummaryStatisticsPivot, fieldConfinement + "0")) == 0: arcpy.AddField_management(tblSummaryStatisticsPivot, fieldConfinement + "0", "DOUBLE") arcpy.CalculateField_management( tblSummaryStatisticsPivot, fieldConfinementValue, "!" + fieldConfinement + "1!/(!" + fieldConfinement + "0! + !" + fieldConfinement + "1!)", "PYTHON") #Pivot Confinement on Segment Size tblSummaryStatisticsWindowPivot = gis_tools.newGISDataset( tempWorkspace, "GNAT_MWA_SummaryStatisticsWindowPivotTable") arcpy.PivotTable_management(tblSummaryStatisticsPivot, fieldStreamRouteID + ";SeedID", "Seg", fieldConfinementValue, tblSummaryStatisticsWindowPivot) # Constriction tblSummaryStatisticsConstriction = gis_tools.newGISDataset( tempWorkspace, "GNAT_MWA_SummaryStatsTableConstriction") arcpy.Statistics_analysis( fcIntersected, tblSummaryStatisticsConstriction, "Shape_Length SUM", fieldStreamRouteID + ";SeedID;Seg;" + fieldConstriction) tblSummaryStatisticsPivotConstriction = gis_tools.newGISDataset( tempWorkspace, "GNAT_MWA_SummaryStatisticsPivotTableConsriction") arcpy.PivotTable_management(tblSummaryStatisticsConstriction, "Route;SeedID;Seg", fieldConstriction, "SUM_Shape_Length", tblSummaryStatisticsPivotConstriction) fieldConstrictionValue = gis_tools.resetField( tblSummaryStatisticsPivotConstriction, "CNST_Value", "DOUBLE") if len( arcpy.ListFields(tblSummaryStatisticsConstriction, fieldConstriction + "1")) == 0: arcpy.AddField_management(tblSummaryStatisticsConstriction, fieldConstriction + "1", "DOUBLE") if len( arcpy.ListFields(tblSummaryStatisticsConstriction, fieldConstriction + "0")) == 0: arcpy.AddField_management(tblSummaryStatisticsConstriction, fieldConstriction + "0", "DOUBLE") arcpy.CalculateField_management( tblSummaryStatisticsPivotConstriction, fieldConstrictionValue, "!" + fieldConstriction + "1!/(!" + fieldConstriction + "0! + !" + fieldConstriction + "1!)", "PYTHON") tblSummaryStatisticsWindowPivotConstriction = gis_tools.newGISDataset( tempWorkspace, "GNAT_MWA_SummaryStatisticsWindowPivotTableConstriction") arcpy.PivotTable_management(tblSummaryStatisticsPivotConstriction, fieldStreamRouteID + ";SeedID", "Seg", fieldConstrictionValue, tblSummaryStatisticsWindowPivotConstriction) strWindowSizeFields = "" for WindowSize in liststrWindowSize: strWindowSizeFields = strWindowSizeFields + ";Seg" + WindowSize strWindowSizeFields = strWindowSizeFields.lstrip(";") #Join Above table to seed points arcpy.JoinField_management(fcSeedPoints, "SeedID", tblSummaryStatisticsWindowPivot, "SeedID", strWindowSizeFields) arcpy.JoinField_management(fcSeedPoints, "SeedID", tblSummaryStatisticsWindowPivotConstriction, "SeedID", strWindowSizeFields) # Manage Outputs fcOutputSeedPoints = gis_tools.newGISDataset(outputWorkspace, "MovingWindowSeedPoints") arcpy.CopyFeatures_management(fcSeedPoints, fcOutputSeedPoints) fcOutputWindows = gis_tools.newGISDataset(outputWorkspace, "MovingWindowSegments") arcpy.CopyFeatures_management(fcWindowLines, fcOutputWindows) return
def main(fcInput, fieldName="Sin", workspaceTmp="in_memory"): # Get list of fields from input feature class keepFields = [keepField.name for keepField in arcpy.ListFields(fcInput)] keepFields.append(fieldName) keepFields.append("InputID") # Prepare inputs fieldInputID = gis_tools.resetField(fcInput, "InputID", "DOUBLE") arcpy.CalculateField_management( fcInput, fieldInputID, "!" + arcpy.Describe(fcInput).OIDFieldName + "!", "PYTHON_9.3") fcInputTmp = gis_tools.newGISDataset(workspaceTmp, "fcIn") arcpy.CopyFeatures_management(fcInput, fcInputTmp) fieldSinuosity = gis_tools.resetField(fcInputTmp, fieldName, "DOUBLE") fieldSegmentLength = gis_tools.resetField(fcInputTmp, "SgLen", "DOUBLE") # Find length of segment arcpy.CalculateField_management(fcInputTmp, fieldSegmentLength, "!shape.length!", "PYTHON_9.3") # Find straight line distance fcSegmentEnds = gis_tools.newGISDataset(workspaceTmp, "SgEnd") arcpy.FeatureVerticesToPoints_management(fcInputTmp, fcSegmentEnds, "BOTH_ENDS") fcSegmentDistances = gis_tools.newGISDataset(workspaceTmp, "SgDst") arcpy.PointsToLine_management(fcSegmentEnds, fcSegmentDistances, fieldInputID) fieldDistance = gis_tools.resetField(fcSegmentDistances, "SgDst", "DOUBLE") arcpy.CalculateField_management(fcSegmentDistances, fieldDistance, "!shape.length!", "PYTHON_9.3") # Join straight line distance feature class lyrInputTmp = gis_tools.newGISDataset("Layer", "lyrInputTmp") arcpy.MakeFeatureLayer_management(fcInputTmp, lyrInputTmp) fieldTmpID = gis_tools.resetField(fcSegmentDistances, "TmpID", "DOUBLE") arcpy.CalculateField_management(fcSegmentDistances, fieldTmpID, "!InputID!", "PYTHON_9.3") arcpy.AddJoin_management(lyrInputTmp, fieldInputID, fcSegmentDistances, fieldTmpID) # Calculate sinuosity codeblock = """def calculateSinuosity(length,distance): if distance == 0: return -9999 else: return length/distance """ arcpy.CalculateField_management( lyrInputTmp, fieldSinuosity, "calculateSinuosity(!" + fieldSegmentLength + "!, !" + fieldDistance + "!)", "PYTHON_9.3", codeblock) # Write Temporary polyline feature class to disk fcOutput = gis_tools.newGISDataset(workspaceTmp, "outputFCSinuosityChannel") arcpy.CopyFeatures_management(lyrInputTmp, fcOutput) dropFields = [dropField.name for dropField in arcpy.ListFields(fcOutput)] arcpy.MakeTableView_management(fcOutput, "fcOutputView") for dropField in dropFields: if dropField not in keepFields: arcpy.DeleteField_management("fcOutputView", dropField) # join final sinuosity output back to input stream network arcpy.MakeFeatureLayer_management(fcInput, "lyrInput") fcInputOID = arcpy.Describe("lyrInput").OIDFieldName arcpy.JoinField_management("lyrInput", fcInputOID, "fcOutputView", "InputID", fieldName) return
def main(fcInputStreamLineNetwork, fcInputValleyBottomPolygon, fcInputChannelPolygon, fcOutputRawConfiningState, fcOutputConfiningMargins, scratchWorkspace, boolIntegratedWidthAttributes=False): ##Prepare processing environments arcpy.AddMessage("Starting Confining Margins Tool") # Create Confined Channel Polygon fcConfinedChannel = gis_tools.newGISDataset(scratchWorkspace, "ChannelConfined") arcpy.Clip_analysis(fcInputChannelPolygon, fcInputValleyBottomPolygon, fcConfinedChannel) # Convert Confined Channel polygon to Edges polyline fcChannelMargins = gis_tools.newGISDataset(scratchWorkspace, "ChannelMargins") arcpy.PolygonToLine_management(fcConfinedChannel, fcChannelMargins) # Create Confinement Edges if fcOutputConfiningMargins: gis_tools.resetData(fcOutputConfiningMargins) fcConfiningMargins = fcOutputConfiningMargins else: fcConfiningMargins = gis_tools.newGISDataset(scratchWorkspace, "ConfiningMargins") fcConfiningMarginsMultipart = gis_tools.newGISDataset( scratchWorkspace, "ConfiningMargins_Multipart") arcpy.Intersect_analysis([fcConfinedChannel, fcInputValleyBottomPolygon], fcConfiningMarginsMultipart, output_type="LINE") arcpy.MultipartToSinglepart_management(fcConfiningMarginsMultipart, fcConfiningMargins) # Merge segments in Polyline Center to create Route Layer arcpy.env.outputZFlag = "Disabled" # 'empty' z values can cause problem with dissolve fcStreamNetworkDissolved = gis_tools.newGISDataset( scratchWorkspace, "StreamNetworkDissolved" ) # one feature per 'section between trib or branch junctions' arcpy.Dissolve_management(fcInputStreamLineNetwork, fcStreamNetworkDissolved, multi_part="SINGLE_PART", unsplit_lines="UNSPLIT_LINES") fcNetworkSegmentPoints = gis_tools.newGISDataset( scratchWorkspace, "StreamNetworkSegmentPoints") arcpy.FeatureVerticesToPoints_management(fcInputStreamLineNetwork, fcNetworkSegmentPoints, "END") fcStreamNetworkDangles = gis_tools.newGISDataset(scratchWorkspace, "StreamNetworkDangles") arcpy.FeatureVerticesToPoints_management(fcInputStreamLineNetwork, fcStreamNetworkDangles, "DANGLE") #SegmentPolgyons arcpy.AddMessage("Preparing Segmented Polygons...") fcChannelSegmentPolygons = gis_tools.newGISDataset(scratchWorkspace, "SegmentPolygons") fcChannelSegmentPolygonLines = gis_tools.newGISDataset( scratchWorkspace, "SegmentPolygonLines") #DividePolygonBySegment.main(fcInputStreamLineNetwork, fcConfinedChannel, fcChannelSegmentPolygons, scratchWorkspace) arcpy.CopyFeatures_management(fcConfinedChannel, fcChannelSegmentPolygons) arcpy.PolygonToLine_management(fcChannelSegmentPolygons, fcChannelSegmentPolygonLines) lyrStreamNetworkDangles = gis_tools.newGISDataset( "LAYER", "lyrStreamNetworkDangles") arcpy.MakeFeatureLayer_management(fcStreamNetworkDangles, lyrStreamNetworkDangles) arcpy.SelectLayerByLocation_management(lyrStreamNetworkDangles, "INTERSECT", fcConfinedChannel) arcpy.Near_analysis(lyrStreamNetworkDangles, fcChannelSegmentPolygonLines, location="LOCATION") arcpy.AddXY_management(lyrStreamNetworkDangles) fcChannelBankNearLines = gis_tools.newGISDataset(scratchWorkspace, "Bank_NearLines") arcpy.XYToLine_management(lyrStreamNetworkDangles, fcChannelBankNearLines, "POINT_X", "POINT_Y", "NEAR_X", "NEAR_Y") fcChannelBankLines = gis_tools.newGISDataset(scratchWorkspace, "Bank_Lines") arcpy.Merge_management([ fcInputStreamLineNetwork, fcChannelBankNearLines, fcChannelSegmentPolygonLines ], fcChannelBankLines) fcChannelBankPolygons = gis_tools.newGISDataset(scratchWorkspace, "Bank_Polygons") arcpy.FeatureToPolygon_management(fcChannelBankLines, fcChannelBankPolygons) # # Intersect and Split Channel polygon Channel Edges and Polyline Confinement using cross section lines arcpy.AddMessage("Intersect and Split Channel Polygons...") fcIntersectPoints_ChannelMargins = gis_tools.newGISDataset( scratchWorkspace, "IntersectPoints_ChannelMargins") fcIntersectPoints_ConfinementMargins = gis_tools.newGISDataset( scratchWorkspace, "IntersectPoints_ConfinementMargins") arcpy.Intersect_analysis( [fcConfiningMargins, fcChannelSegmentPolygonLines], fcIntersectPoints_ConfinementMargins, output_type="POINT") arcpy.Intersect_analysis([fcChannelMargins, fcChannelSegmentPolygonLines], fcIntersectPoints_ChannelMargins, output_type="POINT") fcConfinementMargin_Segments = gis_tools.newGISDataset( scratchWorkspace, "ConfinementMargin_Segments") fcChannelMargin_Segments = gis_tools.newGISDataset( scratchWorkspace, "ChannelMargin_Segements") arcpy.SplitLineAtPoint_management(fcConfiningMargins, fcIntersectPoints_ConfinementMargins, fcConfinementMargin_Segments, search_radius="10 Meters") arcpy.SplitLineAtPoint_management(fcChannelMargins, fcIntersectPoints_ChannelMargins, fcChannelMargin_Segments, search_radius="10 Meters") # Create River Side buffer to select right or left banks arcpy.AddMessage("Determining Relative Sides of Bank...") determine_banks(fcInputStreamLineNetwork, fcChannelBankPolygons, scratchWorkspace) # Prepare Layers for Segment Selection lyrSegmentPolygons = gis_tools.newGISDataset("Layer", "lyrSegmentPolygons") lyrConfinementEdgeSegments = gis_tools.newGISDataset( "Layer", "lyrConfinementEdgeSegments") lyrChannelEdgeSegments = gis_tools.newGISDataset("Layer", "lyrChannelEdgeSegments") arcpy.MakeFeatureLayer_management(fcChannelSegmentPolygons, lyrSegmentPolygons) arcpy.MakeFeatureLayer_management(fcConfinementMargin_Segments, lyrConfinementEdgeSegments) arcpy.MakeFeatureLayer_management(fcChannelMargin_Segments, lyrChannelEdgeSegments) ## Prepare Filtered Margins fcFilterSplitPoints = gis_tools.newGISDataset(scratchWorkspace, "FilterSplitPoints") arcpy.FeatureVerticesToPoints_management(fcConfinementMargin_Segments, fcFilterSplitPoints, "BOTH_ENDS") # Transfer Confining Margins to Stream Network ## arcpy.AddMessage("Transferring Confining Margins to Stream Network...") fcConfinementMarginSegmentsBankSide = gis_tools.newGISDataset( scratchWorkspace, "ConfinementMarginSegmentsBank") lyrConfinementMarginSegmentsBankside = gis_tools.newGISDataset( "Layer", "lyrConfinementMarginSegmentsBankside") field_map = """BankSide "BankSide" true true false 255 Text 0 0 ,First,#,""" + fcChannelBankPolygons + """,BankSide,-1,-1""" arcpy.SpatialJoin_analysis(fcConfinementMargin_Segments, fcChannelBankPolygons, fcConfinementMarginSegmentsBankSide, "JOIN_ONE_TO_ONE", "KEEP_ALL", field_map) arcpy.MakeFeatureLayer_management(fcConfinementMarginSegmentsBankSide, lyrConfinementMarginSegmentsBankside) arcpy.SelectLayerByAttribute_management( lyrConfinementMarginSegmentsBankside, "NEW_SELECTION", """ "BankSide" = 'LEFT'""") fcStreamNetworkConfinementLeft = transfer_line( lyrConfinementMarginSegmentsBankside, fcStreamNetworkDissolved, "LEFT") arcpy.SelectLayerByAttribute_management( lyrConfinementMarginSegmentsBankside, "NEW_SELECTION", """ "BankSide" = 'RIGHT'""") fcStreamNetworkConfinementRight = transfer_line( lyrConfinementMarginSegmentsBankside, fcStreamNetworkDissolved, "RIGHT") fcConfinementStreamNetworkIntersected = gis_tools.newGISDataset( scratchWorkspace, "ConfinementStreamNetworkIntersected") arcpy.Intersect_analysis( [fcStreamNetworkConfinementLeft, fcStreamNetworkConfinementRight], fcConfinementStreamNetworkIntersected, "NO_FID") # TODO no fid? #Re-split centerline by segments arcpy.AddMessage("Determining Confinement State on Stream Network...") fcRawConfiningNetworkSplit = gis_tools.newGISDataset( scratchWorkspace, "RawConfiningNetworkSplit") arcpy.SplitLineAtPoint_management(fcConfinementStreamNetworkIntersected, fcNetworkSegmentPoints, fcRawConfiningNetworkSplit, "0.01 Meters") #Table and Attributes arcpy.AddField_management(fcRawConfiningNetworkSplit, "Con_Type", "TEXT", field_length="6") arcpy.AddField_management(fcRawConfiningNetworkSplit, "IsConfined", "SHORT") gis_tools.resetField(fcRawConfiningNetworkSplit, "IsConstric", "SHORT") lyrRawConfiningNetwork = gis_tools.newGISDataset( "Layer", "lyrStreamNetworkCenterline1") arcpy.MakeFeatureLayer_management(fcRawConfiningNetworkSplit, lyrRawConfiningNetwork) arcpy.SelectLayerByAttribute_management(lyrRawConfiningNetwork, "NEW_SELECTION", """ "Con_LEFT" = 1""") arcpy.CalculateField_management(lyrRawConfiningNetwork, "Con_Type", "'LEFT'", "PYTHON") arcpy.SelectLayerByAttribute_management(lyrRawConfiningNetwork, "NEW_SELECTION", """ "Con_RIGHT" = 1""") arcpy.CalculateField_management(lyrRawConfiningNetwork, "Con_Type", "'RIGHT'", "PYTHON") arcpy.SelectLayerByAttribute_management( lyrRawConfiningNetwork, "NEW_SELECTION", """ "Con_LEFT" = 1 AND "Con_RIGHT" = 1""") arcpy.CalculateField_management(lyrRawConfiningNetwork, "Con_Type", "'BOTH'", "PYTHON") arcpy.CalculateField_management(lyrRawConfiningNetwork, "IsConstric", "1", "PYTHON") arcpy.SelectLayerByAttribute_management(lyrRawConfiningNetwork, "SWITCH_SELECTION") arcpy.CalculateField_management(lyrRawConfiningNetwork, "IsConstric", "0", "PYTHON") arcpy.SelectLayerByAttribute_management( lyrRawConfiningNetwork, "NEW_SELECTION", """ "Con_LEFT" = 1 OR "Con_RIGHT" = 1""") arcpy.CalculateField_management(lyrRawConfiningNetwork, "IsConfined", "1", "PYTHON") arcpy.SelectLayerByAttribute_management(lyrRawConfiningNetwork, "SWITCH_SELECTION") arcpy.CalculateField_management(lyrRawConfiningNetwork, "IsConfined", "0", "PYTHON") arcpy.CalculateField_management(lyrRawConfiningNetwork, "Con_Type", "'NONE'", "PYTHON") # Integrated Width fcIntersectLineNetwork = fcInputStreamLineNetwork if boolIntegratedWidthAttributes: fcIntegratedChannelWidth = gis_tools.newGISDataset( scratchWorkspace, "IW_Channel") fieldIWChannel = integrated_width(fcInputStreamLineNetwork, fcChannelSegmentPolygons, fcIntegratedChannelWidth, "Channel", False) fcIntegratedWidth = gis_tools.newGISDataset(scratchWorkspace, "IW_ChannelAndValley") fieldIWValley = integrated_width(fcIntegratedChannelWidth, fcInputValleyBottomPolygon, fcIntegratedWidth, "Valley", True) fieldIWRatio = gis_tools.resetField(fcIntegratedWidth, "IW_Ratio", "DOUBLE") exp = "!" + fieldIWValley + r"! / !" + fieldIWChannel + "!" arcpy.CalculateField_management(fcIntegratedWidth, fieldIWRatio, exp, "PYTHON_9.3") fcIntersectLineNetwork = fcIntegratedWidth # Final Output arcpy.AddMessage("Preparing Final Output...") if arcpy.Exists(fcOutputRawConfiningState): arcpy.Delete_management(fcOutputRawConfiningState) arcpy.Intersect_analysis( [fcRawConfiningNetworkSplit, fcIntersectLineNetwork], fcOutputRawConfiningState, "NO_FID") return
def main(fcInputStreamLineNetwork, fcInputValleyBottomPolygon, fcInputChannelPolygon, filterByLength, fcOutputRawConfiningState, fcOutputConfiningMargins, scratchWorkspace, boolIntegratedWidthAttributes=False): ''' Description: Main processing function for creating the confinement margins and segmenting the network. Updated: 24/8/18 - DDH - Now returns True/False if code succeeds or fails, this can be used by calling module 5/9/18 - DDH - Now uses FilterByLength to delete out confinement margins created by the intersection that fall below the specified length. Default is 5m 6/9/18 - DDH - Creates MarginID field and purges out all other fields except Length ''' try: ##Prepare processing environments arcpy.AddMessage("Starting Confining Margins Tool") # Create Confined Channel Polygon # This clips the channel polygon by the valley botton polygon arcpy.AddMessage("... Clipping channel polygon with Valley bottom") fcConfinedChannel = gis_tools.newGISDataset(scratchWorkspace, "ChannelConfined") arcpy.Clip_analysis(fcInputChannelPolygon, fcInputValleyBottomPolygon, fcConfinedChannel) # Convert Confined Channel polygon to Edges polyline arcpy.AddMessage( "... Converting clipped channel polygon to a polyline dataset") fcChannelMargins = gis_tools.newGISDataset(scratchWorkspace, "ChannelMargins") arcpy.PolygonToLine_management(fcConfinedChannel, fcChannelMargins) # Create Confinement Edges if fcOutputConfiningMargins: gis_tools.resetData(fcOutputConfiningMargins) fcConfiningMargins = fcOutputConfiningMargins else: fcConfiningMargins = gis_tools.newGISDataset( scratchWorkspace, "ConfiningMargins") arcpy.AddMessage( "... Intersecting clipped channel polygon with valley bottom returning intersection lines" ) fcConfiningMarginsMultipart = gis_tools.newGISDataset( scratchWorkspace, "ConfiningMargins_Multipart") arcpy.Intersect_analysis( [fcConfinedChannel, fcInputValleyBottomPolygon], fcConfiningMarginsMultipart, output_type="LINE") arcpy.MultipartToSinglepart_management(fcConfiningMarginsMultipart, fcConfiningMargins) # Delete lines that fall below the specified length if filterByLength > 0: # Make a temporary layer, select lines and delete arcpy.AddMessage("... Adding Length field and updating") arcpy.MakeFeatureLayer_management(fcConfiningMargins, "tempLayer") arcpy.AddField_management("tempLayer", "Length", "DOUBLE") arcpy.CalculateField_management("tempLayer", "Length", "!SHAPE.length@METERS!", "PYTHON_9.3") arcpy.AddMessage("... Selecting lines smaller than " + str(filterByLength) + "m and deleting") arcpy.SelectLayerByAttribute_management( "tempLayer", "NEW_SELECTION", '"' + "Length" + '"' + " <= " + str(filterByLength)) descObj = arcpy.Describe("tempLayer") if len(descObj.FIDSet) > 0: # A Selection exists so delete arcpy.DeleteFeatures_management("tempLayer") # Clean up del descObj arcpy.Delete_management("tempLayer") else: arcpy.AddMessage( "Filter by Length parameter was set to 0m, skipping deleting features" ) # Merge segments in Polyline Centerline to create Route Layer arcpy.AddMessage("... Dissolving stream network into routes") arcpy.env.outputZFlag = "Disabled" # 'empty' z values can cause problem with dissolve fcStreamNetworkDissolved = gis_tools.newGISDataset( scratchWorkspace, "StreamNetworkDissolved" ) # one feature per 'section between trib or branch junctions' arcpy.Dissolve_management(fcInputStreamLineNetwork, fcStreamNetworkDissolved, multi_part="SINGLE_PART", unsplit_lines="UNSPLIT_LINES") arcpy.AddMessage("... Extracting stream network END points") fcNetworkSegmentPoints = gis_tools.newGISDataset( scratchWorkspace, "StreamNetworkSegmentPoints") arcpy.FeatureVerticesToPoints_management(fcInputStreamLineNetwork, fcNetworkSegmentPoints, "END") arcpy.AddMessage("... Extracting stream network DANGLE points") fcStreamNetworkDangles = gis_tools.newGISDataset( scratchWorkspace, "StreamNetworkDangles") arcpy.FeatureVerticesToPoints_management(fcInputStreamLineNetwork, fcStreamNetworkDangles, "DANGLE") #SegmentPolgyons arcpy.AddMessage("Preparing Segmented Polygons...") fcChannelSegmentPolygons = gis_tools.newGISDataset( scratchWorkspace, "SegmentPolygons") fcChannelSegmentPolygonLines = gis_tools.newGISDataset( scratchWorkspace, "SegmentPolygonLines") arcpy.AddMessage( "... Copying clipped channel polygon and converting to polyline dataset" ) #DividePolygonBySegment.main(fcInputStreamLineNetwork, fcConfinedChannel, fcChannelSegmentPolygons, scratchWorkspace) arcpy.CopyFeatures_management(fcConfinedChannel, fcChannelSegmentPolygons) arcpy.PolygonToLine_management(fcChannelSegmentPolygons, fcChannelSegmentPolygonLines) arcpy.AddMessage("... Building proximity information for DANGLES") lyrStreamNetworkDangles = gis_tools.newGISDataset( "LAYER", "lyrStreamNetworkDangles") arcpy.MakeFeatureLayer_management(fcStreamNetworkDangles, lyrStreamNetworkDangles) arcpy.SelectLayerByLocation_management(lyrStreamNetworkDangles, "INTERSECT", fcConfinedChannel) arcpy.Near_analysis(lyrStreamNetworkDangles, fcChannelSegmentPolygonLines, location="LOCATION") arcpy.AddXY_management(lyrStreamNetworkDangles) arcpy.AddMessage("... Building bank lines") fcChannelBankNearLines = gis_tools.newGISDataset( scratchWorkspace, "Bank_NearLines") arcpy.XYToLine_management(lyrStreamNetworkDangles, fcChannelBankNearLines, "POINT_X", "POINT_Y", "NEAR_X", "NEAR_Y") fcChannelBankLines = gis_tools.newGISDataset(scratchWorkspace, "Bank_Lines") arcpy.Merge_management([ fcInputStreamLineNetwork, fcChannelBankNearLines, fcChannelSegmentPolygonLines ], fcChannelBankLines) fcChannelBankPolygons = gis_tools.newGISDataset( scratchWorkspace, "Bank_Polygons") arcpy.FeatureToPolygon_management(fcChannelBankLines, fcChannelBankPolygons) # Intersect and Split Channel polygon Channel Edges and Polyline Confinement using cross section lines arcpy.AddMessage("Intersect and Split Channel Polygons...") fcIntersectPoints_ChannelMargins = gis_tools.newGISDataset( scratchWorkspace, "IntersectPoints_ChannelMargins") fcIntersectPoints_ConfinementMargins = gis_tools.newGISDataset( scratchWorkspace, "IntersectPoints_ConfinementMargins") arcpy.Intersect_analysis( [fcConfiningMargins, fcChannelSegmentPolygonLines], fcIntersectPoints_ConfinementMargins, output_type="POINT") arcpy.Intersect_analysis( [fcChannelMargins, fcChannelSegmentPolygonLines], fcIntersectPoints_ChannelMargins, output_type="POINT") fcConfinementMargin_Segments = gis_tools.newGISDataset( scratchWorkspace, "ConfinementMargin_Segments") fcChannelMargin_Segments = gis_tools.newGISDataset( scratchWorkspace, "ChannelMargin_Segements") arcpy.SplitLineAtPoint_management(fcConfiningMargins, fcIntersectPoints_ConfinementMargins, fcConfinementMargin_Segments, search_radius="10 Meters") arcpy.SplitLineAtPoint_management(fcChannelMargins, fcIntersectPoints_ChannelMargins, fcChannelMargin_Segments, search_radius="10 Meters") # Create River Side buffer to select right or left banks arcpy.AddMessage("Determining Relative Sides of Bank...") determine_banks(fcInputStreamLineNetwork, fcChannelBankPolygons, scratchWorkspace) # Prepare Layers for Segment Selection lyrSegmentPolygons = gis_tools.newGISDataset("Layer", "lyrSegmentPolygons") lyrConfinementEdgeSegments = gis_tools.newGISDataset( "Layer", "lyrConfinementEdgeSegments") lyrChannelEdgeSegments = gis_tools.newGISDataset( "Layer", "lyrChannelEdgeSegments") arcpy.MakeFeatureLayer_management(fcChannelSegmentPolygons, lyrSegmentPolygons) arcpy.MakeFeatureLayer_management(fcConfinementMargin_Segments, lyrConfinementEdgeSegments) arcpy.MakeFeatureLayer_management(fcChannelMargin_Segments, lyrChannelEdgeSegments) ## Prepare Filtered Margins fcFilterSplitPoints = gis_tools.newGISDataset(scratchWorkspace, "FilterSplitPoints") arcpy.FeatureVerticesToPoints_management(fcConfinementMargin_Segments, fcFilterSplitPoints, "BOTH_ENDS") # Transfer Confining Margins to Stream Network ## arcpy.AddMessage("Transferring Confining Margins to Stream Network...") fcConfinementMarginSegmentsBankSide = gis_tools.newGISDataset( scratchWorkspace, "ConfinementMarginSegmentsBank") lyrConfinementMarginSegmentsBankside = gis_tools.newGISDataset( "Layer", "lyrConfinementMarginSegmentsBankside") field_map = """BankSide "BankSide" true true false 255 Text 0 0 ,First,#,""" + fcChannelBankPolygons + """,BankSide,-1,-1""" arcpy.SpatialJoin_analysis(fcConfinementMargin_Segments, fcChannelBankPolygons, fcConfinementMarginSegmentsBankSide, "JOIN_ONE_TO_ONE", "KEEP_ALL", field_map) arcpy.MakeFeatureLayer_management( fcConfinementMarginSegmentsBankSide, lyrConfinementMarginSegmentsBankside) arcpy.SelectLayerByAttribute_management( lyrConfinementMarginSegmentsBankside, "NEW_SELECTION", """ "BankSide" = 'LEFT'""") fcStreamNetworkConfinementLeft = transfer_line( lyrConfinementMarginSegmentsBankside, fcStreamNetworkDissolved, "LEFT") arcpy.SelectLayerByAttribute_management( lyrConfinementMarginSegmentsBankside, "NEW_SELECTION", """ "BankSide" = 'RIGHT'""") fcStreamNetworkConfinementRight = transfer_line( lyrConfinementMarginSegmentsBankside, fcStreamNetworkDissolved, "RIGHT") # This intersection step combines the two outputs from transfer_line() into a single dataset using intersection arcpy.AddMessage("... Constructing segmented stream network") fcConfinementStreamNetworkIntersected = gis_tools.newGISDataset( scratchWorkspace, "ConfinementStreamNetworkIntersected") arcpy.Intersect_analysis( [fcStreamNetworkConfinementLeft, fcStreamNetworkConfinementRight], fcConfinementStreamNetworkIntersected, "NO_FID") # TODO no fid? #Re-split centerline by segments arcpy.AddMessage("Determining Confinement State on Stream Network...") fcRawConfiningNetworkSplit = gis_tools.newGISDataset( scratchWorkspace, "RawConfiningNetworkSplit") arcpy.SplitLineAtPoint_management( fcConfinementStreamNetworkIntersected, fcNetworkSegmentPoints, fcRawConfiningNetworkSplit, "0.01 Meters") #Table and Attributes arcpy.AddMessage("... Adding fields and attributing") arcpy.AddField_management(fcRawConfiningNetworkSplit, "Con_Type", "TEXT", field_length="6") arcpy.AddField_management(fcRawConfiningNetworkSplit, "IsConfined", "SHORT") gis_tools.resetField(fcRawConfiningNetworkSplit, "IsConstric", "SHORT") lyrRawConfiningNetwork = gis_tools.newGISDataset( "Layer", "lyrStreamNetworkCenterline1") arcpy.MakeFeatureLayer_management(fcRawConfiningNetworkSplit, lyrRawConfiningNetwork) arcpy.SelectLayerByAttribute_management(lyrRawConfiningNetwork, "NEW_SELECTION", """ "Con_LEFT" = 1""") arcpy.CalculateField_management(lyrRawConfiningNetwork, "Con_Type", "'LEFT'", "PYTHON") arcpy.SelectLayerByAttribute_management(lyrRawConfiningNetwork, "NEW_SELECTION", """ "Con_RIGHT" = 1""") arcpy.CalculateField_management(lyrRawConfiningNetwork, "Con_Type", "'RIGHT'", "PYTHON") arcpy.SelectLayerByAttribute_management( lyrRawConfiningNetwork, "NEW_SELECTION", """ "Con_LEFT" = 1 AND "Con_RIGHT" = 1""") arcpy.CalculateField_management(lyrRawConfiningNetwork, "Con_Type", "'BOTH'", "PYTHON") arcpy.CalculateField_management(lyrRawConfiningNetwork, "IsConstric", "1", "PYTHON") arcpy.SelectLayerByAttribute_management(lyrRawConfiningNetwork, "SWITCH_SELECTION") arcpy.CalculateField_management(lyrRawConfiningNetwork, "IsConstric", "0", "PYTHON") arcpy.SelectLayerByAttribute_management( lyrRawConfiningNetwork, "NEW_SELECTION", """ "Con_LEFT" = 1 OR "Con_RIGHT" = 1""") arcpy.CalculateField_management(lyrRawConfiningNetwork, "IsConfined", "1", "PYTHON") arcpy.SelectLayerByAttribute_management(lyrRawConfiningNetwork, "SWITCH_SELECTION") arcpy.CalculateField_management(lyrRawConfiningNetwork, "IsConfined", "0", "PYTHON") arcpy.CalculateField_management(lyrRawConfiningNetwork, "Con_Type", "'NONE'", "PYTHON") # Integrated Width # This code is never executed as the Boolean is ALWAYS FALSE! fcIntersectLineNetwork = fcInputStreamLineNetwork if boolIntegratedWidthAttributes: fcIntegratedChannelWidth = gis_tools.newGISDataset( scratchWorkspace, "IW_Channel") fieldIWChannel = integrated_width(fcInputStreamLineNetwork, fcChannelSegmentPolygons, fcIntegratedChannelWidth, "Channel", False) fcIntegratedWidth = gis_tools.newGISDataset( scratchWorkspace, "IW_ChannelAndValley") fieldIWValley = integrated_width(fcIntegratedChannelWidth, fcInputValleyBottomPolygon, fcIntegratedWidth, "Valley", True) fieldIWRatio = gis_tools.resetField(fcIntegratedWidth, "IW_Ratio", "DOUBLE") exp = "!" + fieldIWValley + r"! / !" + fieldIWChannel + "!" arcpy.CalculateField_management(fcIntegratedWidth, fieldIWRatio, exp, "PYTHON_9.3") fcIntersectLineNetwork = fcIntegratedWidth # Final Output arcpy.AddMessage("Preparing Final Output...") if arcpy.Exists(fcOutputRawConfiningState): arcpy.Delete_management(fcOutputRawConfiningState) arcpy.Intersect_analysis( [fcRawConfiningNetworkSplit, fcIntersectLineNetwork], fcOutputRawConfiningState, "NO_FID") # Call function to clean up fields and add additional attribution to confinement margins layer arcpy.AddMessage("Cleaning up confinement margins layer...") bOK = prepConfinementOutput(fcConfiningMargins, fcConfinementMarginSegmentsBankSide) if not bOK: arcpy.AddWarning( "An error occurred whilst preparing Confinement Margins layer!" ) arcpy.AddWarning( "Make sure it has a valid MarginID and Length field") return True except arcpy.ExecuteError: # Geoprocessor threw an error arcpy.AddError(arcpy.GetMessages(2)) return False except Exception as e: arcpy.AddError("Error in ConfiningMargins main function: " + str(e)) return False