In questo caso sono tre i problemi da affrontare:
- fori
- Linee tra poligoni
- Linee di fondo
fori
Poiché qualsiasi linea all'interno di un foro verrà mantenuta, rimuovere i fori dai poligoni. Nella sceneggiatura sotto lo faccio usando cursori e geometrie.
Linee tra poligoni
Le linee che toccano due poligoni devono essere rimosse. Nello script seguente lo faccio eseguendo un join spaziale di one to many
, con le mie linee come la mia classe di funzionalità di input e i miei poligoni come la mia classe di funzionalità di join. Ogni linea che viene generata due volte tocca due poligoni e viene rimossa.
Linee di fondo
Per rimuovere le linee che toccano solo un poligono su un'estremità, converto le linee in punti finali. Quindi uso i feature layer e le selezioni per determinare quali punti finali sono mobili. Seleziono i punti finali che intersecano i poligoni. Quindi cambio la mia selezione. Seleziona i punti finali che non intersecano i poligoni. Seleziono qualsiasi linea che interseca questi punti selezionati e li elimino.
Risultato
ipotesi
- Gli input sono classi di caratteristiche di geodatabase di file
- La licenza avanzata ArcGIS è disponibile (a causa di un
erase
e un feature vertices to points
)
- Le linee continue e connesse sono un'unica funzione
- I poligoni non si sovrappongono
- Non ci sono poligoni multipart
copione
Lo script seguente mostra una classe caratteristica con il nome della classe caratteristica linea più _GreedyClip
, nello stesso geodatabase della classe caratteristica linea. È inoltre necessaria una posizione dell'area di lavoro.
#input polygon feature class
polyFc = r"C:\Users\e1b8\Desktop\E1B8\Workspace\Workspace.gdb\testPolygon2"
#input line feature class
lineFc = r"C:\Users\e1b8\Desktop\E1B8\Workspace\Workspace.gdb\testLine"
#workspace
workspace = r"in_memory"
print "importing"
import arcpy
import os
#generate a unique ArcGIS file name
def UniqueFileName(location = "in_memory", name = "file", extension = ""):
if extension:
outName = os.path.join (location, name + "." + extension)
else:
outName = os.path.join (location, name)
i = 0
while arcpy.Exists (outName):
i += 1
if extension:
outName = os.path.join (location, "{0}_{1}.{2}".format (name, i, extension))
else:
outName = os.path.join (location, "{0}_{1}".format (name, i))
return outName
#remove holes from polygons
def RemoveHoles (inFc, workspace):
outFc = UniqueFileName (workspace)
array = arcpy.Array ()
sr = arcpy.Describe (inFc).spatialReference
outPath, outName = os.path.split (outFc)
arcpy.CreateFeatureclass_management (outPath, outName, "POLYGON", spatial_reference = sr)
with arcpy.da.InsertCursor (outFc, "SHAPE@") as iCurs:
with arcpy.da.SearchCursor (inFc, "SHAPE@") as sCurs:
for geom, in sCurs:
try:
part = geom.getPart (0)
except:
continue
for pnt in part:
if not pnt:
break
array.add (pnt)
polygon = arcpy.Polygon (array)
array.removeAll ()
row = (polygon,)
iCurs.insertRow (row)
del iCurs
del sCurs
return outFc
#split line fc by polygon fc
def SplitLinesByPolygon (lineFc, polygonFc, workspace):
#clip
clipFc = UniqueFileName(workspace)
arcpy.Clip_analysis (lineFc, polygonFc, clipFc)
#erase
eraseFc = UniqueFileName(workspace)
arcpy.Erase_analysis (lineFc, polygonFc, eraseFc)
#merge
mergeFc = UniqueFileName(workspace)
arcpy.Merge_management ([clipFc, eraseFc], mergeFc)
#multipart to singlepart
outFc = UniqueFileName(workspace)
arcpy.MultipartToSinglepart_management (mergeFc, outFc)
#delete intermediate data
for trash in [clipFc, eraseFc, mergeFc]:
arcpy.Delete_management (trash)
return outFc
#remove lines between two polygons and end lines
def RemoveLines (inFc, polygonFc, workspace):
#check if "TARGET_FID" is in fields
flds = [f.name for f in arcpy.ListFields (inFc)]
if "TARGET_FID" in flds:
#delete "TARGET_FID" field
arcpy.DeleteField_management (inFc, "TARGET_FID")
#spatial join
sjFc = UniqueFileName(workspace)
arcpy.SpatialJoin_analysis (inFc, polygonFc, sjFc, "JOIN_ONE_TO_MANY")
#list of TARGET_FIDs
targetFids = [fid for fid, in arcpy.da.SearchCursor (sjFc, "TARGET_FID")]
#target FIDs with multiple occurances
deleteFids = [dFid for dFid in targetFids if targetFids.count (dFid) > 1]
if deleteFids:
#delete rows with update cursor
with arcpy.da.UpdateCursor (inFc, "OID@") as cursor:
for oid, in cursor:
if oid in deleteFids:
cursor.deleteRow ()
del cursor
#feature vertices to points
vertFc = UniqueFileName(workspace)
arcpy.FeatureVerticesToPoints_management (inFc, vertFc, "BOTH_ENDS")
#select points intersecting polygons
arcpy.MakeFeatureLayer_management (vertFc, "vertLyr")
arcpy.SelectLayerByLocation_management ("vertLyr", "", polygonFc, "1 FEET")
#switch selection
arcpy.SelectLayerByAttribute_management ("vertLyr", "SWITCH_SELECTION")
arcpy.MakeFeatureLayer_management (inFc, "lineLyr")
#check for selection
if arcpy.Describe ("vertLyr").FIDSet:
#select lines by selected points
arcpy.SelectLayerByLocation_management ("lineLyr", "", "vertLyr", "1 FEET")
#double check selection (should always have selection)
if arcpy.Describe ("lineLyr").FIDSet:
#delete selected rows
arcpy.DeleteFeatures_management ("lineLyr")
#delete intermediate data
for trash in [sjFc, "vertLyr", "lineLyr"]:
arcpy.Delete_management (trash)
#main script
def main (polyFc, lineFc, workspace):
#remove holes
print "removing holes"
holelessPolyFc = RemoveHoles (polyFc, workspace)
#split line at polygons
print "splitting lines at polygons"
splitFc = SplitLinesByPolygon (lineFc, holelessPolyFc, workspace)
#delete unwanted lines
print "removing unwanted lines"
RemoveLines (splitFc, polyFc, workspace)
#create output feature class
outFc = lineFc + "_GreedyClip"
outFcPath, outFcName = os.path.split (outFc)
outFc = UniqueFileName (outFcPath, outFcName)
arcpy.CopyFeatures_management (splitFc, outFc)
print "created:"
print outFc
print
print "cleaning up"
#delete intermediate data
for trash in [holelessPolyFc, splitFc]:
arcpy.Delete_management (trash)
print "done"
if __name__ == "__main__":
main (polyFc, lineFc, workspace)