I have to generate thousands of cells as a grid, and then I have to assign values to the cells, so far I know the a fishnet tool can generate the grid but how can I manage to create the offset. May some one have better Idea.
The details of the grid are as illustrated in the attached diagram.
I have 5 Rows and 6 column, after the 3rd column the grid should start with B, other numbering should be the same as A.
Solved! Go to Solution.
You are absolutely correct, I mean labeling, and almost exactly right correct in your all other assumptions.
Thank you
You could try this:
def main():
import arcpy
import os
# settings
fc_out = r'C:\GeoNet\RectangleBlocks\data.gdb\result04'
fld_lbl = r'RectangleID'
sr = arcpy.SpatialReference(2276) # NAD_1983_StatePlane_Texas_North_Central_FIPS_4202_Feet?
x_start = 2523853.5 # lower left
y_start = 7124354.1 # lower left
rect_width = 10.0
rect_height = 5.0
num_blocks_h = 6
num_blocks_v = 5
num_rect_in_block_h = 4
num_rect_in_block_v = 8
spacing_h = 3.0
spacing_v = 3.0
# create output featureclass
arcpy.env.overwriteOutput = True
fc_ws, fc_name = os.path.split(fc_out)
arcpy.CreateFeatureclass_management(fc_ws, fc_name, "POLYGON", None, None, None, sr)
# add field
arcpy.AddField_management(fc_out, fld_lbl, "TEXT", None, None, 10)
# insert cursor
flds = ("SHAPE@", fld_lbl)
cnt = 0
with arcpy.da.InsertCursor(fc_out, flds) as curs:
# loop through blocks
for block_h in range(num_blocks_h):
for block_v in range(num_blocks_v):
# loop through rectangles
for rect_h in range(num_rect_in_block_h):
for rect_v in range(num_rect_in_block_v):
x_min = x_start + block_h * spacing_h + block_h * num_rect_in_block_h * rect_width + rect_h * rect_width
y_min = y_start + block_v * spacing_v + block_v * num_rect_in_block_v * rect_height + rect_v * rect_height
x_max = x_min + rect_width
y_max = y_min + rect_height
rectangle = CreateRactangle(x_min, y_min, x_max, y_max, sr)
label = GetLabel(block_h, block_v, rect_h, rect_v)
cnt += 1
if cnt % 50 == 0:
print("Processing rectangle: {}".format(cnt))
curs.insertRow((rectangle, label, ))
print("Finished processing {} rectangles".format(cnt))
def CreateRactangle(x_min, y_min, x_max, y_max, sr):
coords = [[x_min, y_min], [x_min, y_max], [x_max, y_max],
[x_max, y_min], [x_min, y_min]]
return arcpy.Polygon(arcpy.Array([arcpy.Point(*coord) for coord in coords]), sr)
def GetLabel(block_h, block_v, rect_h, rect_v):
even = rect_h % 2 == 0
if rect_v < 4:
# lower
if even:
part3 = rect_v + 1
else:
part3 = rect_v + 5
quad_row = 1 + 12 * block_v
if rect_h <2:
quad_col = block_h * 2
else:
# lower right
quad_col = 1 + block_h * 2
else:
if even:
part3 = rect_v - 3
else:
part3 = rect_v + 1
quad_row = 7 + 12 * block_v
if rect_h <2:
quad_col = block_h * 2
else:
# lower right
quad_col = 1 + block_h * 2
part2 = quad_row + quad_col
if block_h < 3:
part1 = "A"
else:
part1 = "B"
part2 = part2 - 6
return "{}-{}-{}".format(part1, part2, part3)
if __name__ == '__main__':
main()
Which results in:
Xander
This script saved my day a couple of times
one line of your script I had never used before.
return "{}-{}-{}".format(part1, part2, part3)
format is it a method to concatenate string elements.
"Thank you" does not even begin to express the gratitude I have for this help.
It has been around for a while...
Read all about it
/blogs/dan_patterson/2016/03/01/basic-fancy-formats
From the Python docs
6.1. string — Common string operations — Python 3.7.0 documentation
Thank you, for the Useful Link
In short the line:
return "{}-{}-{}".format(part1, part2, part3)
... will take a string "{}-{}-{}" and will replace each "{}" by a parameters specified in the format. A very easy and powerful feature of Python. I recommend that you read the documentation provided by the links in Dan_Patterson 's comment.
Thanks, Dan Patterson 's comment very useful
I am playing around this script, I am not quite well understanding the second part (creating the label - starting from
GetLabel function). If you could put some comments on this parts,
def GetLabel(block_h, block_v, rect_h, rect_v):
even = rect_h % 2 == 0
if rect_v < 4:
# lower
if even:
part3 = rect_v + 1
else:
part3 = rect_v + 5
quad_row = 1 + 12 * block_v
if rect_h <2:
quad_col = block_h * 2
else:
# lower right
quad_col = 1 + block_h * 2
else:
if even:
part3 = rect_v - 3
else:
part3 = rect_v + 1
quad_row = 7 + 12 * block_v
if rect_h <2:
quad_col = block_h * 2
else:
# lower right
quad_col = 1 + block_h * 2
part2 = quad_row + quad_col
if block_h < 3:
part1 = "C"
else:
part1 = "D"
part2 = part2 - 6
return "{}-{}-{}".format(part1, part2, part3)
I am trying to modify this part so the label goes straight through C only without D section and without the offset,
Thank You
See below the snippet with some comments:
def GetLabel(block_h, block_v, rect_h, rect_v):
# 4 parameters necessary:
# - block_h = block number horizontally
# - block_v = block number vertically
# - rect_h = rectangle number horizontally
# - rect_v = rectangle number vertically
# determine if the rectangle number horizontally is even or uneven
even = rect_h % 2 == 0
# devide the block vertically in two halves
if rect_v < 4:
# lower 4 rectangle lines inside a block
if even:
# determine the 3rd part of the label
# values 0 + 1 to 3 + 1 -> (1 - 4)
part3 = rect_v + 1
else:
# values 0 + 5 to 3 + 5 -> (5 - 8)
part3 = rect_v + 5
# determine the quadrant of the block (in rows)
# for instance the second block (=1 when starting to count at 0) vertically
# will result in 1 + 12 * 1 = 13 (which is where the lower left starts
# see "A-13-1"
quad_row = 1 + 12 * block_v
# determine the quadrant of the block (in cols)
if rect_h <2:
# left part of block
quad_col = block_h * 2
else:
# right part of block
quad_col = 1 + block_h * 2
else:
# do the same for the upper 4 rectangle lines inside a block
if even:
part3 = rect_v - 3
else:
part3 = rect_v + 1
quad_row = 7 + 12 * block_v
if rect_h <2:
quad_col = block_h * 2
else:
# lower right
quad_col = 1 + block_h * 2
# part 2 of the label is the result of adding quad_row and quad_col
part2 = quad_row + quad_col
if block_h < 3:
# for first 3 blocks horizontally, assign an "A"
part1 = "A"
else:
# otherwise assign a "B" and correct part 2 of the label
part1 = "B"
part2 = part2 - 6
# construct the label combing the 3 parts
return "{}-{}-{}".format(part1, part2, part3)
Ï'm a little confused about your comment to go straight to "C without "D". "D" would only occur when there are more than 9 blocks horizontally. Does that happen? I assume to include the "C" you would have to replace the else on line 54 with an elif block_h < 6 and add the else on line 58 assigning "C" to part 1 and probably applying some corrections to part2 (run it and see what the value should be).
Thank you Xander,
I am still did not get it, now my scenario is changed I am only have one section now, and no spacing
x_start = 2523853.5 # lower left
y_start = 7124354.1 # lower left
rect_width = 10.0
rect_height = 5.0
num_blocks_h = 7
num_blocks_v = 7
num_rect_in_block_h = 4
num_rect_in_block_v = 8
spacing_h = 0.0
spacing_v = 0.0
and here is the complete code, but I have some logic errors, see the Red in the Results (Repeating row no)
def main():
import arcpy
import os
# settings
fc_out = r'C:\HH\ce\cemeterypy.gdb\result05'
fld_lbl = r'RectangleID'
sr = arcpy.SpatialReference(2276) # NAD_1983_StatePlane_Texas_North_Central_FIPS_4202_Feet?
x_start = 2523853.5 # lower left
y_start = 7124354.1 # lower left
rect_width = 10.0
rect_height = 5.0
num_blocks_h = 7
num_blocks_v = 7
num_rect_in_block_h = 4
num_rect_in_block_v = 8
spacing_h = 0.0
spacing_v = 0.0
# create output featureclass
arcpy.env.overwriteOutput = True
fc_ws, fc_name = os.path.split(fc_out)
arcpy.CreateFeatureclass_management(fc_ws, fc_name, "POLYGON", None, None, None, sr)
# add field
arcpy.AddField_management(fc_out, fld_lbl, "TEXT", None, None, 10)
# insert cursor
flds = ("SHAPE@", fld_lbl)
cnt = 0
with arcpy.da.InsertCursor(fc_out, flds) as curs:
# loop through blocks
for block_h in range(num_blocks_h):
for block_v in range(num_blocks_v):
# loop through rectangles
for rect_h in range(num_rect_in_block_h):
for rect_v in range(num_rect_in_block_v):
x_min = x_start + block_h * spacing_h + block_h * num_rect_in_block_h * rect_width + rect_h * rect_width
y_min = y_start + block_v * spacing_v + block_v * num_rect_in_block_v * rect_height + rect_v * rect_height
x_max = x_min + rect_width
y_max = y_min + rect_height
rectangle = CreateRactangle(x_min, y_min, x_max, y_max, sr)
label = GetLabel(block_h, block_v, rect_h, rect_v)
cnt += 1
if cnt % 50 == 0:
print("Processing rectangle: {}".format(cnt))
curs.insertRow((rectangle, label, ))
print("Finished processing {} rectangles".format(cnt))
def CreateRactangle(x_min, y_min, x_max, y_max, sr):
coords = [[x_min, y_min], [x_min, y_max], [x_max, y_max],
[x_max, y_min], [x_min, y_min]]
return arcpy.Polygon(arcpy.Array([arcpy.Point(*coord) for coord in coords]), sr)
def GetLabel(block_h, block_v, rect_h, rect_v):
# 4 parameters necessary:
# - block_h = block number horizontally
# - block_v = block number vertically
# - rect_h = rectangle number horizontally
# - rect_v = rectangle number vertically
# determine if the rectangle number horizontally is even or uneven
even = rect_h % 2 == 0
# devide the block vertically in two halves
if rect_v < 4:
# lower 4 rectangle lines inside a block
if even:
# determine the 3rd part of the label
# values 0 + 1 to 3 + 1 -> (1 - 4)
part3 = rect_v + 1
else:
# values 0 + 5 to 3 + 5 -> (5 - 8)
part3 = rect_v + 5
# determine the quadrant of the block (in rows)
# for instance the second block (=1 when starting to count at 0) vertically
# will result in 1 + 12 * 1 = 13 (which is where the lower left starts
# see "A-13-1"
quad_row = 1 + 14 * block_v
# determine the quadrant of the block (in cols)
if rect_h <2:
# left part of block
quad_col = block_h * 2
else:
# right part of block
quad_col = 1 + block_h * 2
else:
# do the same for the upper 4 rectangle lines inside a block
if even:
part3 = rect_v - 3
else:
part3 = rect_v + 1
quad_row = 15 + 14 * block_v
if rect_h <2:
quad_col = block_h * 2
else:
# lower right
quad_col = 1 + block_h * 2
# part 2 of the label is the result of adding quad_row and quad_col
part2 = quad_row + quad_col
if block_h < 7:
# for first 3 blocks horizontally, assign an "A"
part1 = "A"
else:
# otherwise assign a "B" and correct part 2 of the label
part1 = "B"
part2 = part2 - 7
# construct the label combing the 3 parts
return "{}-{}-{}".format(part1, part2, part3)
if __name__ == '__main__':
main()
Result
Thank you