Lo he intentado en ArcMap porque no sé cómo hacerlo en QGIS. Tal vez alguien más puede traducir las ideas en QGIS. Estoy usando ArcGIS 10.4 con licencia avanzada (Avanzado es necesario para la herramienta de borrado que se utiliza en script).
script a continuación dividirá todos los polígonos de una clase de característica de entrada en cinco partes de área casi iguales. Área casi igual porque el script no comprueba que todas las partes tengan exactamente la misma área, sólo que el área de cada parte esté dentro de un margen de error especificado.
Si el polígono que se procesa es redondo, se dividirá como un pastel:
Si no es redonda, es alargada y se dividirá así:
Pero no así (divisiones no paralelas):
Ejemplo:
Código:
import arcpy,math
arcpy.env.workspace = r'C:\TEST.gdb'
arcpy.env.overwriteOutput = 1
infc = r'polygons'
outfc = r'divided_polygons'
totalpolycount = arcpy.GetCount_management(infc)
polygoncount = 0
partcount = 1
with arcpy.da.SearchCursor(infc,['SHAPE@AREA','SHAPE@LENGTH','SHAPE@XY','SHAPE@']) as scursor1:
for srow1 in scursor1:
polygoncount+=1
print "Processing polygon {} of {}".format(polygoncount,totalpolycount)
#Find out if polygon is round (compactness >=0.045) or elongated
compactness = srow1[0]/(srow1[1]**2)
if compactness >= 0.045:
print "It's round, dividing like a cake"
dist=srow1[1] #/2
radian=0.0
trailingcoord = [srow1[2][0],srow1[2][1]+dist]
for j in range(1,6):
unloopcounter=0
areadiff=99999.0
#Keep increasing angle of cakepiece until difference in area between piece and 1/5 of polygon is below 1/2000 of polygon area
while abs(areadiff)>(srow1[0]/2000) and unloopcounter<5000:
radian+=0.002
feature_info = [list(srow1[2]), trailingcoord]
if j<5:
feature_info.append([srow1[2][0]+dist*math.sin(radian),srow1[2][1]+dist*math.cos(radian)])
else:
feature_info.append([srow1[2][0],srow1[2][1]+dist])
unloopcounter=9999
polygontemp=arcpy.Polygon(arcpy.Array([arcpy.Point(*coords) for coords in feature_info]))
arcpy.Clip_analysis(srow1[3],polygontemp, r'in_memory\polygonpart')
with arcpy.da.SearchCursor(r'in_memory\polygonpart',['SHAPE@AREA']) as scursor2:
for srow2 in scursor2:
areadiff=srow1[0]/5-srow2[0]
unloopcounter+=1
print 'Part {} took {} attempts'.format(j, unloopcounter)
trailingcoord=[srow1[2][0]+dist*math.sin(radian),srow1[2][1]+dist*math.cos(radian)]
arcpy.CopyFeatures_management(r'in_memory\polygonpart','Polygon_'+str(polygoncount)+'_Part_'+str(j))
else:
print "It's elongated, dividing like a bread loaf"
arcpy.MinimumBoundingGeometry_management(srow1[3],r'in_memory\bounding','RECTANGLE_BY_WIDTH')
arcpy.SplitLine_management(r'in_memory\bounding', r'in_memory\splitline')
linelist=[]
with arcpy.da.SearchCursor(r'in_memory\splitline',['SHAPE@LENGTH','SHAPE@']) as scursor3:
for srow3 in scursor3:
linelist.append(srow3)
linelist=sorted(linelist,key=lambda x: x[0])
deltax = linelist[3][1].firstPoint.X-linelist[3][1].lastPoint.X
deltay = linelist[3][1].firstPoint.Y-linelist[3][1].lastPoint.Y
with arcpy.da.UpdateCursor(r'in_memory\bounding',['SHAPE@XY']) as ucursor1:
for urow1 in ucursor1:
shiftx=0.0
shifty=0.0
for i in range(1,6):
areadiff = 99999
unloopcounter = 0
arcpy.Clip_analysis(srow1[3], r'in_memory\bounding', r'in_memory\boundingclip')
#keep moving bounding polygon until the differnce between piece left after erase and 1/5 of polygon is below 1/2000 of polygon area
while abs(areadiff) > (srow1[0]/2000) and unloopcounter < 5000:
if i==5:
shiftx+=deltax
shifty+=deltay
unloopcounter=9999
ucursor1.updateRow([[urow1[0][0]+shiftx,urow1[0][1]+shifty]])
shiftx+=deltax/5000
shifty+=deltay/5000
arcpy.Erase_analysis(r'in_memory\boundingclip', r'in_memory\bounding', r'in_memory\polygonpart')
with arcpy.da.SearchCursor(r'in_memory\polygonpart',['SHAPE@AREA']) as scursor4:
for srow4 in scursor4:
areadiff = (srow1[0]/5)-srow4[0]
unloopcounter+=1
print "Part {} took {} attempts".format(i,unloopcounter)
arcpy.CopyFeatures_management(r'in_memory\polygonpart', out_feature_class='Polygon_'+str(polygoncount)+'_Part_'+str(i))
print "Merging all the parts together, deleting temp data and repairing small gaps"
partlist = arcpy.ListFeatureClasses(wild_card='Polygon_*')
arcpy.Merge_management(partlist, outfc)
for part in partlist:
arcpy.Delete_management(part)
arcpy.Integrate_management(outfc, 0.001) #The dividing sometime creates small gaps between parts. Gaps smaller than 0.001 m are repaired (change the 0.001 if needed).
print "Finished"
3 votos
¿Podrías añadir una captura de pantalla o, mejor aún, subir tu shapefile a un servidor público para que otros puedan probarlo?
1 votos
Supongo que lo mejor es que hagas un dibujo de lo que tienes y lo que quieres. Para mí, la pregunta no es muy clara.
1 votos
¿En qué sentido quiere dividir la ciudad en 5 regiones?
0 votos
Lo siento, he añadido algunas fotos para explicarlo mejor. Espero que ahora esté claro.
0 votos
Parcel Fabric ofrece un polígono, dividir por igual-área. help.arcgis.com/es/arcgisdesktop/10.0/help/index.html#/
0 votos
¿Qué valoras en términos de solución? El pequeño ejemplo que proporcionas muestra dos esquemas diferentes. El ejemplo de la izquierda tiene las divisiones de la subregión colocadas radialmente alrededor del centroide de la subregión. El ejemplo de la derecha tiene las divisiones orientadas perpendicularmente a un eje principal de la subregión. ¿Se prefiere uno de estos métodos a otro? ¿Es importante la topología? ¿Pueden las subregiones tener formas complejas con agujeros?
0 votos
Me gustaría hacer algo parecido a esto: bl.ocks.org/mbostock/8814734 . Pero las zonas originales (primera foto) son bastante grandes y me gustaría dividirlas.