Di chuyển huyền thoại nếu nó chồng lấp các tính năng trong khung dữ liệu bằng ArcPy


8

Cố gắng tìm cách lập trình (arcpy) di chuyển huyền thoại nếu nó chặn các tính năng trong khung dữ liệu, trong kịch bản bên dưới, nếu huyền thoại che khuất tầm nhìn của AOI, thì tôi muốn nó di chuyển đến một góc khác cho đến khi nó không phải là một vấn đề. Điều này phải được đặt lên trên cùng của khung dữ liệu chứ không phải làm cho khung dữ liệu nhỏ hơn và chỉ đặt nó sang một bên.

nhập mô tả hình ảnh ở đây


1
Nếu bạn đang sử dụng Trang hướng dữ liệu, bạn có thể tìm thấy một số trợ giúp trong việc này: gis.stackexchange.com/questions/167975/ . Nói chung, tôi sẽ tìm kiếm Google trên một cái gì đó như "di chuyển huyền thoại trong các trang hướng dữ liệu" để biết thêm một số gợi ý. Với các truyền thuyết cố định, tôi đã chuyển đổi chúng thành một hình ảnh và sử dụng các cách sau để di chuyển chúng xung quanh: support.esri.com/en/technical-article/000011951 Không ai trong số này là câu trả lời, chỉ là cách giải quyết.
johns

Có tôi hiện đang sử dụng các trang điều khiển dữ liệu, cảm ơn vì liên kết Johns
Slevy

Câu trả lời:


7

Đầu vào: nhập mô tả hình ảnh ở đây Kịch bản:

import arcpy, traceback, os, sys, time
from arcpy import env
import numpy as np
env.overwriteOutput = True
outFolder=arcpy.GetParameterAsText(0)
env.workspace = outFolder
dpi=2000
tempf=r'in_memory\many'
sj=r'in_memory\sj'
## ERROR HANDLING
def showPyMessage():
    arcpy.AddMessage(str(time.ctime()) + " - " + message)
try:
    mxd = arcpy.mapping.MapDocument("CURRENT")
    allLayers=arcpy.mapping.ListLayers(mxd,"*")
    ddp = mxd.dataDrivenPages
    df = arcpy.mapping.ListDataFrames(mxd)[0]
    SR = df.spatialReference
##  GET LEGEND ELEMENT
    legendElm = arcpy.mapping.ListLayoutElements(mxd, "LEGEND_ELEMENT", "myLegend")[0]
#   GET PAGES INFO
    thePagesLayer = arcpy.mapping.ListLayers(mxd,ddp.indexLayer.name)[0]
    fld = ddp.pageNameField.name
#   SHUFFLE THROUGH PAGES
    for pageID in range(1, ddp.pageCount+1):
        ddp.currentPageID = pageID
        aPage=ddp.pageRow.getValue(fld)
        arcpy.RefreshActiveView()
##      DEFINE WIDTH OF legend IN MAP UNITS..
        E=df.extent
        xmin=df.elementPositionX;xmax=xmin+df.elementWidth
        x=[xmin,xmax];y=[E.XMin,E.XMax]
        aX,bX=np.polyfit(x, y, 1)
        w=aX*legendElm.elementWidth
##      and COMPUTE NUMBER OF ROWS FOR FISHNET
        nRows=(E.XMax-E.XMin)//w
##      DEFINE HEIGHT OF legend IN MAP UNITS
        ymin=df.elementPositionY;ymax=ymin+df.elementHeight
        x=[ymin,ymax];y=[E.YMin,E.YMax]
        aY,bY=np.polyfit(x, y, 1)
        h=aY*legendElm.elementHeight
##      and COMPUTE NUMBER OF COLUMNS FOR FISHNET
        nCols=(E.YMax-E.YMin)//h
##      CREATE FISHNET WITH SLIGHTLY BIGGER CELLS (due to different aspect ratio between legend and dataframe)
        origPoint='%s %s' %(E.XMin,E.YMin)
        yPoint='%s %s' %(E.XMin,E.YMax)
        endPoint='%s %s' %(E.XMax,E.YMax)
        arcpy.CreateFishnet_management(tempf, origPoint,yPoint,
                                       "0", "0", nCols, nRows,endPoint,
                                       "NO_LABELS", "", "POLYGON")
        arcpy.DefineProjection_management(tempf, SR)
##      CHECK CORNER CELLS ONLY
        arcpy.SpatialJoin_analysis(tempf, tempf, sj, "JOIN_ONE_TO_ONE",
                                   match_option="SHARE_A_LINE_SEGMENT_WITH")
        nCorners=0
        with arcpy.da.SearchCursor(sj, ("Shape@","Join_Count")) as cursor:
            for shp, neighbours in cursor:
                if neighbours!=3:continue
                nCorners+=1; N=0
                for lyr in allLayers:
                    if not lyr.visible:continue
                    if lyr.isGroupLayer:continue
                    if not lyr.isFeatureLayer:continue
##      CHECK IF THERE ARE FEATURES INSIDE CORNER CELL
                    arcpy.Clip_analysis(lyr, shp, tempf)
                    result=arcpy.GetCount_management(tempf)
                    n=int(result.getOutput(0))
                    N+=n
                    if n>0: break
##      IF NONE, CELL FOUND; COMPUTE PAGE COORDINATES FOR LEGEND AND BREAK
                if N==0:
                    tempRaster=outFolder+os.sep+aPage+".png"
                    e=shp.extent;X=e.XMin;Y=e.YMin
                    x=(X-bX)/aX;y=(Y-bY)/aY
                    break
        if nCorners==0: N=1
##      IF NO CELL FOUND PLACE LEGEND OUTSIDE DATAFRAME
        if N>0:
            x=df.elementPositionX+df.elementWidth
            y=df.elementPositionY
        legendElm.elementPositionY=y
        legendElm.elementPositionX=x
        outFile=outFolder+os.sep+aPage+".png"
        arcpy.AddMessage(outFile)
        arcpy.mapping.ExportToPNG(mxd,outFile)
except:
    message = "\n*** PYTHON ERRORS *** "; showPyMessage()
    message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
    message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()

ĐẦU RA: nhập mô tả hình ảnh ở đây

GHI CHÚ: Đối với mỗi trang trong các trang điều khiển dữ liệu, tập lệnh cố gắng tìm đủ chỗ trong các góc khung dữ liệu để đặt Chú thích (được gọi là myLegend) mà không che bất kỳ lớp tính năng hiển thị nào. Script sử dụng fishnet để xác định các ô góc. Kích thước ô lớn hơn một chút so với kích thước Huyền thoại trong các đơn vị xem dữ liệu. Ô góc là cái có chung ranh giới với 3 hàng xóm. Nếu không tìm thấy góc hoặc phòng, Chú thích được đặt bên ngoài khung dữ liệu trên trang bố cục.

Thật không may, tôi không biết cách quản lý truy vấn định nghĩa trang. Các điểm được hiển thị ban đầu nằm rải rác xung quanh phạm vi RECTANGLE, với một số trong số chúng không có liên kết với các trang. Arcpy vẫn nhìn thấy toàn bộ lớp, mặc dù tôi đã áp dụng truy vấn định nghĩa (khớp) cho các điểm.


Cảm ơn bạn đã viết rất nhiều về Felix này, mặc dù tôi gặp vấn đề khi triển khai giải pháp này để làm việc linh hoạt như ví dụ của bạn, chi tiết như thế này, có bất cứ điều gì tôi nên biết khi tạo tài liệu bản đồ, các điểm neo huyền thoại, v.v. ?
Kiểu dáng đẹp

1
Các điểm neo ở phía dưới bên trái cho cả chú giải và khung dữ liệu. Làm thế nào tôi quên điều này?
FelixIP

Đúng, chắc chắn đã tạo ra một sự khác biệt trong thử nghiệm ở đây. Nếu tôi muốn chuyển điểm neo sang giữa (đối với khung dữ liệu), tôi có cho rằng toàn bộ logic đã hết không? phần nào tôi cần cấu hình. Chỉ dòng 33 đến 44?
Kiểu dáng đẹp

1
Tính xmin và xmax qua chiều rộng và vị trí x. Tương tự với trục y. Không chắc chắn tại sao bạn cần nó ...
FelixIP

Một phần của quy trình làm việc khác, cảm ơn Felix, bước tiến tuyệt vời ở đây
Slevy

3

Cách mà tôi sẽ làm điều này là tạo ra một lớp tính năng "yếu tố huyền thoại" đại diện cho yếu tố huyền thoại của bạn trong cùng hệ thống tọa độ với các tính năng đó.

Bằng cách đó, bạn có thể sử dụng Chọn lớp theo vị trí để kiểm tra xem phần tử chú giải của bạn có trùng với bất kỳ tính năng nào không và di chuyển nó nếu có.

Nó không tầm thường nhưng có thể thực hiện được và có một câu hỏi và trả lời trên trang web này ( Chuyển đổi điểm XY sang đơn vị trang XY bằng arcpy? ) Có thể được sử dụng để giải quyết phần khó nhất khi chuyển đổi giữa tọa độ trang và bản đồ.


1
Phần khó nhất là tìm khoảng cách đủ lớn để lắp hộp huyền thoại.
FelixIP

1
@FelixIP Tại sao vậy? Có vẻ như người hỏi đang tự giới hạn mình chỉ kiểm tra bốn góc của khung dữ liệu. Tôi cho rằng họ có một quy tắc cho những gì xảy ra nếu không có góc nào phù hợp.
PolyGeo

Tôi nghĩ rằng đây là cách để đi, mặc dù khoảng cách trong truyền thuyết có lẽ sẽ là vấn đề nhỏ nhất của tôi. Lý tưởng nhất là tỷ lệ bản đồ sẽ tiếp tục thay đổi cho đến khi huyền thoại không chặn được đa giác quan tâm. Mặc dù muốn nghe hoặc xem một số ví dụ thực tế mọi người đã cố gắng!
Kiểu dáng đẹp

2

Dưới đây là mã tôi đã sử dụng để di chuyển các huyền thoại và bản đồ chèn để không làm mờ dữ liệu. Bạn đã hỏi về chức năng kiểm tra giao nhau trên một chủ đề khác. Đây là việc tôi thực hiện mã của người khác. Tôi không nhớ chính xác nó đến từ đâu. Tôi nghĩ đó là một kịch bản để di chuyển bản đồ nội bộ cho một tiểu bang ở New England.

inset là phần xử lý cho phần tử chú thích hoặc phần tử bản đồ.

#check intersect function


def checkIntersect(MovableObject):

    #get absolute x and y disatnce of MovableObject in page units
    PageOriginDistX = (inset.elementPositionX + inset.elementWidth) - DataFrame.elementPositionX #Xmax in page units
    PageOriginDistY = (inset.elementPositionY + inset.elementHeight) - DataFrame.elementPositionY #absolute y disatnce of element


    #Generate x/y pairs for new tempfile used to test intersection of original MovableObject placement
    Xmax = DataFrame.extent.XMin + ((DataFrame.extent.XMax - DataFrame.extent.XMin) *
                                    (PageOriginDistX / DataFrame.elementWidth))
    Xmin = DataFrame.extent.XMin + ((DataFrame.extent.XMax - DataFrame.extent.XMin) *
                                    ((inset.elementPositionX - DataFrame.elementPositionX) / DataFrame.elementWidth))
    Ymax = DataFrame.extent.YMin + ((DataFrame.extent.YMax - DataFrame.extent.YMin) *
                                    (PageOriginDistY / DataFrame.elementHeight))
    Ymin = DataFrame.extent.YMin + ((DataFrame.extent.YMax - DataFrame.extent.YMin) *
                                    ((inset.elementPositionY - DataFrame.elementPositionY) / DataFrame.elementHeight))


    #list of coords for temp polygon
    coordList = [[[Xmax,Ymax], [Xmax,Ymin], [Xmin,Ymin], [Xmin,Ymax]]]
    #create empty temp poly as tempShape, give it a spatial ref, make it into a featureclass so it works
    #with intersect
    tempShape = os.path.join(sys.path[0], "temp.shp")
    arcpy.CreateFeatureclass_management(sys.path[0], "temp.shp","POLYGON")
    array = arcpy.Array()
    point = arcpy.Point()
    featureList = []

    arcpy.env.overwriteOutput = True
    for feature in coordList:
        for coordPair in feature:
            point.X = coordPair[0]
            point.Y = coordPair[1]
            array.add(point)     
        array.add(array.getObject(0))    
        polygon = arcpy.Polygon(array)    
        array.removeAll()
        featureList.append(polygon)

    arcpy.CopyFeatures_management(featureList, tempShape)
    arcpy.MakeFeatureLayer_management(tempShape, "tempShape_lyr")

    #check for intersect
    arcpy.SelectLayerByLocation_management("unobscured_lyr", "INTERSECT",   "tempShape_lyr", "", "NEW_SELECTION")

    #initiate search and count
    polyCursor = arcpy.SearchCursor("unobscured_lyr")
    polyRow = polyCursor.next()
    count = 0

    #Clear Selection
    arcpy.SelectLayerByAttribute_management("unobscured_lyr","CLEAR_SELECTION")

    #Delete the temporary shapefile.
    arcpy.Delete_management(tempShape)

    #count
    while polyRow:
        count = count + 1
        polyRow = polyCursor.next()


    #Clear Selection
    arcpy.SelectLayerByAttribute_management("unobscured_lyr","CLEAR_SELECTION")

    #Delete the temporary shapefile.
    arcpy.Delete_management(tempShape)

    #Return the count value to main part of script to determine placement of locator map.
    return count

Sau đó, mã dưới đây từ bài đăng này ( Các trang hướng dữ liệu với Bản đồ di chuyển / Bản đồ khởi động ) sẽ có ý nghĩa hơn.

for pageNum in range(1, mxd.dataDrivenPages.pageCount + 1):
#setup naming and path for output maps
path = mxd.filePath
bn = os.path.basename(path)[:-4]
mxd.dataDrivenPages.currentPageID = pageNum   

insetDefaultX = inset.elementPositionX
insetDefaultY = inset.elementPositionY

#check defualt position for intersect
intersect = checkIntersect(inset)

if intersect == 0: #if it doesn't intersect, print the map
    arcpy.mapping.ExportToEPS(mxd, exportFolder + "\\" + bn + "_"+ str(pageNum) + ".eps", "Page_Layout",640,480,300,"BETTER","RGB",3,"ADAPTIVE","RASTERIZE_BITMAP",True,False)

else: #intersect != 0: #move inset to SE corner
    inset.elementPositionX = (DataFrame.elementPositionX + DataFrame.elementWidth) - inset.elementWidth
    inset.elementPositionY = DataFrame.elementPositionY

1
nên đề cập: trong ví dụ này phần tử được neo ở phía dưới bên trái.
CSB

Cảm ơn CSB, Có cho trường hợp của tôi, tôi cần khung dữ liệu được neo ở giữa, vì vậy tôi đang trong quá trình tùy chỉnh công thức mở rộng Trang gốc của bạn, tôi sẽ đăng lên ví dụ khi tôi đến đó. Nếu không, trông rất hứa hẹn trong thử nghiệm ban đầu. Ngoài ra, có tham chiếu đến "unobscured_lyr", giả sử điều này được tham chiếu bên ngoài tập lệnh là lớp cần tránh?
Kiểu dáng đẹp

chính xác, "unobscured_lyr" là cái chúng tôi đang cố gắng không bao gồm. Tất nhiên, bạn cũng có thể làm cho nó hoạt động với nhiều lớp.
CSB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.