sAnSiBaR Posted January 16, 2017 Report Share Posted January 16, 2017 Hi all, I need some help with python code and buffer in ArcGIS: A set of polygons (all in one featureclass, circular shapes) should get several buffers (e.g. 40 times). Each feature gets a different buffer distance, it is stored in corresponding field in attribute table. So the first buffer distance is taken from value in table, the following are calculated by "buffer*i", "i" is counting from 1 to 40. For example: If first feature has the value 400 metres, first buffer for that feature would be 400 metres, 2nd 800 metres, 3rd 1200 metres,.... (measured from the origin shape). I had two attempts, both are not working the way I like: import arcpy arcpy.env.workspace = r"R:\Base.gdb" fc = "export" fieldname = "Buffer" i = 1 while i <= 40: outName = fc+"_" + str(i) dist = (fieldname)*i arcpy.Buffer_analysis(fc, outName, dist) i = i+1 Result: First Buffer OK, then abortion, because cannot find fieldname "BufferBuffer" (sure, multiplication of fieldname, but how to calculate with value and not with the name?). import arcpy arcpy.env.workspace = r"R:\Base.gdb" fc = "export" fieldname = "Buffer" cursor = arcpy.SearchCursor(fc) row = cursor.next() i = 1 while i <= 40: outName = fc+"_" + str(i) dist = row.getValue(fieldname)*i arcpy.Buffer_analysis(fc, outName, dist) i = i+1 Result: No Abortion, but all buffers are calculated based on one value from first feature in attribute table, not the corresponding. In case of using QGis, there are some plugins for multiple buffer, but they work just with static values. Maybe it's just a short fix in code, who could help me? Quote Link to comment Share on other sites More sharing options...
3dbu Posted January 16, 2017 Report Share Posted January 16, 2017 Check the Script of multi ring buffer: """---------------------------------------------------------------------------------- Tool Name: Multiple Ring Buffer Source Name: MultiRingBuffer.py Author: Environmental Systems Research Institute Inc. Required Arguments: An input feature class or feature layer An output feature class A set of distances (multiple set of double values) Optional Arguments: The name of the field to contain the distance values (default="distance") Option to have the output dissolved (default="ALL") Description: Creates a set of buffers for the set of input features. The buffers are defined using a set of variable distances. The resulting feature class has the merged buffer polygons with or without overlapping polygons maintained as separate features. ----------------------------------------------------------------------------------""" import arcpy import os import locale # Define message constants so they may be translated easily msgBuffRings = arcpy.GetIDMessage(86149) # "Buffering distance " msgMergeRings = arcpy.GetIDMessage(86150) # "Merging rings..." msgDissolve = arcpy.GetIDMessage(86151) # "Dissolving overlapping boundaries..." def initiate_multi_buffer(): """Gather arguments and set up for createMultiBuffers""" # Get the input argument values in_features = arcpy.GetParameterAsText(0) output = arcpy.GetParameterAsText(1) distances = arcpy.GetParameter(2) unit = arcpy.GetParameterAsText(3) if unit.lower() == 'default': unit = '' field_name = checkfieldname(arcpy.GetParameterAsText(4), os.path.dirname(output)) dissolve_type = arcpy.GetParameterAsText(5) outside_polygons = arcpy.GetParameterAsText(6) if outside_polygons.lower() == 'true': side_type = 'OUTSIDE_ONLY' else: side_type = '' create_multi_buffers(in_features, output, distances, unit, field_name, dissolve_type, side_type) def checkfieldname(field_name, workspace): """Validate field name on the workspace as needed""" if field_name in ['#', '']: return "distance" else: out_name = arcpy.ValidateFieldName(field_name, workspace) out_name = out_name.replace(' ', '_') if out_name != field_name: arcpy.AddIDMessage('WARNING', 648, out_name) return out_name def lower_license_union(feature_classes): """If Union is not licensed for more than 2 inputs at a time, perform Unions in batches""" union_fc = None tmp_fc = arcpy.Union_analysis( feature_classes[0:2], arcpy.CreateUniqueName('union', arcpy.env.scratchGDB))[0] for fc in feature_classes[2:]: if union_fc: tmp_fc = union_fc union_fc = arcpy.Union_analysis( [tmp_fc, fc], arcpy.CreateUniqueName('union', arcpy.env.scratchGDB))[0] # Delete intermediate data once used by next Union try: arcpy.Delete_management(tmp_fc) except arcpy.ExecuteError: # Don't fail for a delete issue pass return union_fc def create_multi_buffers(in_features, output, distances, unit, field_name, dissolve_type, side_type): """Main multiple ring buffer routine""" # Establish place holders for data cleanup buffer_list = [] union_fc = None try: # Loop through each distance creating a new layer and then buffering the input. # Set the step progressor if there are > 1 rings if len(distances) > 1: arcpy.SetProgressor('step', '', 0, len(distances)) step_progressor = True else: arcpy.SetProgressor('default') step_progressor = False # Buffer the input for each buffer distance. If the field_name is different than # the default, add a new field and calculate the proper value for dist in distances: if step_progressor: arcpy.SetProgressorPosition() arcpy.SetProgressorLabel(msgBuffRings + '{}...'.format(dist)) buf_distance = '{} {}'.format(dist, unit) buf_output = arcpy.Buffer_analysis(in_features, arcpy.CreateUniqueName('buffer', arcpy.env.scratchGDB), buf_distance, side_type, '', dissolve_type)[0] buffer_list.append(buf_output) if field_name.lower() != 'buff_dist': arcpy.AddField_management(buf_output, field_name, 'double') arcpy.CalculateField_management(buf_output, field_name, dist, 'PYTHON') arcpy.ResetProgressor() arcpy.SetProgressor('default') arcpy.SetProgressorLabel(msgMergeRings) if dissolve_type == 'ALL': # Set up the expression and codeblock variables for CalculateField to ensure # the distance field is populated properly expression = 'pullDistance({}, '.format(distances) for fc in buffer_list: expression += '!FID_{}!, '.format(os.path.basename(fc)) expression = expression[:-2] + ')' # If we have a full license then Union all feature classes at once, otherwise # Union the feature classes 2 at a time if arcpy.ProductInfo().upper() in ['ARCINFO', 'ARCSERVER'] or len(buffer_list) < 3: union_fc = arcpy.Union_analysis(buffer_list, arcpy.CreateUniqueName('union', arcpy.env.scratchGDB))[0] codeblock = '''def pullDistance(distL, *fids): return min([i for i, j in zip(distL, fids) if j != -1])''' else: union_fc = lower_license_union(buffer_list) codeblock = '''def pullDistance(distL, *fids): return min([i for i, j in zip(distL, fids) if j == 1])''' arcpy.CalculateField_management(union_fc, field_name, expression, 'PYTHON', codeblock) # Complete the final Dissolve arcpy.SetProgressorLabel(msgDissolve) if dissolve_type.upper() == 'ALL': arcpy.Dissolve_management(union_fc, output, field_name) else: # Reverse the order of the inputs so the features are appended from # largest to smallest buffer features. buffer_list.reverse() template = buffer_list[0] sr = (arcpy.env.outputCoordinateSystem or arcpy.Describe(template).spatialreference) arcpy.CreateFeatureclass_management(os.path.dirname(output), os.path.basename(output), 'POLYGON', template, 'SAME_AS_TEMPLATE', 'SAME_AS_TEMPLATE', sr) for fc in buffer_list: arcpy.Append_management(fc, output, 'NO_TEST') if arcpy.ListFields(output, 'buff_dist'): # Remove duplicate field arcpy.DeleteField_management(output, 'buff_dist') # Set the default symbology params = arcpy.GetParameterInfo() if len(params) > 0: params[1].symbology = os.path.join(arcpy.GetInstallInfo()['InstallDir'], "arctoolbox\\templates\\layers\\multipleringbuffer.lyr") except arcpy.ExecuteError: arcpy.AddError(arcpy.GetMessages(2)) except Exception as err: arcpy.AddError(err) finally: if buffer_list: for fc in buffer_list: try: arcpy.Delete_management(fc) except arcpy.ExecuteError: # Don't fail for a delete issue pass if union_fc: try: arcpy.Delete_management(union_fc) except arcpy.ExecuteError: # Don't fail for a delete issue pass if __name__ == '__main__': initiate_multi_buffer() Quote Link to comment Share on other sites More sharing options...
sAnSiBaR Posted January 16, 2017 Author Report Share Posted January 16, 2017 Thanks! I'll have a look on it. Quote Link to comment Share on other sites More sharing options...
yousef2233 Posted January 17, 2017 Report Share Posted January 17, 2017 (edited) I think you should use cursors like this input_fc="fc" field = "buffer_value_field" output = "fc_somewhere" output_temp = "fc_somewhereElse" cursor = arcpy.da.SearchCursor(input_fc) for row in cursor: arcpy.analysis.Buffer(input_fc,row.getValue(field),output_temp) arcpy.management.Append(output_temp,output,"NO_TEST") arcpy.management.Delete(output_temp) it does not work in the append process, I just made a conceptual example for you Edited January 17, 2017 by yousef2233 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.