Có ba vấn đề cần giải quyết trong trường hợp này:
- Hố
- Các đường giữa các đa giác
- Dòng kết thúc
Hố
Vì bất kỳ dòng nào trong một lỗ sẽ được duy trì, hãy loại bỏ các lỗ khỏi đa giác. Trong kịch bản dưới đây, tôi làm như vậy bằng cách sử dụng con trỏ và hình học.
Các đường giữa các đa giác
Các dòng chạm hai đa giác cần phải được loại bỏ. Trong kịch bản bên dưới, tôi làm như vậy bằng cách thực hiện phép nối không gian one to many
, với các dòng của tôi là lớp tính năng đầu vào và đa giác của tôi là lớp tính năng tham gia của tôi. Bất kỳ dòng nào được tạo hai lần chạm vào hai đa giác và được loại bỏ.
Dòng kết thúc
Để xóa các dòng chỉ chạm vào một đa giác ở một đầu, tôi chuyển đổi các dòng thành điểm cuối. Sau đó tôi sử dụng các lớp tính năng và các lựa chọn để xác định điểm cuối nào là dấu phao. Tôi chọn các điểm cuối giao nhau với đa giác. Sau đó tôi chuyển đổi lựa chọn của mình. Điều này chọn điểm cuối không giao nhau đa giác. Tôi chọn bất kỳ dòng nào giao nhau với các điểm đã chọn và xóa chúng.
Kết quả
Giả định
- Đầu vào là các lớp tính năng cơ sở dữ liệu địa lý
- Giấy phép nâng cao ArcGIS có sẵn (do một
erase
và a feature vertices to points
)
- Các đường liên tục, được kết nối là một tính năng duy nhất
- Đa giác không trùng nhau
- Không có đa giác nhiều phần
Kịch bản
Tập lệnh bên dưới xuất ra một lớp đối tượng với tên của lớp đối tượng đường cộng của bạn _GreedyClip
, trong cùng cơ sở dữ liệu địa lý với lớp đối tượng đường dây của bạn. Một vị trí không gian làm việc cũng cần thiết.
#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)