У цьому випадку можна вирішити три питання:
- Отвори
- Лінії між багатокутниками
- Кінцеві лінії
Отвори
Оскільки будь-яка лінія в отворі буде підтримуватися, видаліть отвори з багатокутників. У нижченаведеному сценарії я роблю це за допомогою курсорів та геометрій.
Лінії між багатокутниками
Лінії, які торкаються двох багатокутників, потрібно видалити. У нижченаведеному сценарії я це роблю, виконуючи просторове з'єднання one to many
з моїми рядками, як мій клас вхідних ознак, і мої полігони як мій клас функції об'єднання. Будь-яка лінія, яка утворюється двічі, торкається двох многокутників і видаляється.
Кінцеві лінії
Щоб видалити лінії, які торкаються лише багатокутника на одному кінці, я перетворюю лінії в кінцеві точки. Потім я використовую функціональні шари та вибір, щоб визначити, які кінцеві точки є плавцями. Я вибираю кінцеві точки, що перетинаються багатокутники. Потім я перемикаю свій вибір. Це вибирає кінцеві точки, які не перетинаються багатокутників. Я вибираю будь-який рядок, який перетинає ці вибрані точки, і видаляю їх.
Результат
Припущення
- Вхідні дані - це файлові класи функцій бази даних геоданих
- Доступна розширена ліцензія ArcGIS (завдяки та
erase
і feature vertices to points
)
- Безперервні, з'єднані лінії - це одна особливість
- Полігони не перетинаються
- Немає багаточастинних багатокутників
Сценарій
Сценарій, наведений нижче, виводить клас функції з назвою вашого класу функцій рядка плюс _GreedyClip
у тій самій базі геоданих, що і ваш клас функцій рядка. Також потрібне розташування робочої області.
#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)