Python'dan ArcObjects kullanma yönergeleri


10

By kadar Python gelen ArcObject erişme? GIS Stack Exchange'de en çok okunan ve başvurulan Soru ve Cevap. Bu başarıya rağmen, gerçek kullanım söz konusu olduğunda muhtemelen en zayıf bölgelerimden biri. Bu kötü gösterimin büyük bir kısmı, ArcObjects belgelerini okuma ve anlama yeteneğimin yetersizliğinden kaynaklanıyor .

Peki, herhangi bir görev için .net / c ++ / java / ... belgelerini ve örneklerini python eşdeğerlerine çevirmek için bazı yönergeler nelerdir? (bu konuda çalışmak için en iyi dil hangisidir?) ve başlamak için en iyi dizin veya açılış sayfası hangisidir? hangi şeylere odaklanmalı ve en azından aynı derecede önemli olarak, neleri özgürce göz ardı edilebilir?

Kitlenizin en azından biraz python okuryazar olduğunu ve diğer geliştirme dillerinde okuma yazma bilmediğini varsayalım. İlk fikirden ve araştırmadan, çalışan python sonuçlarına kadar küçük bir kodlama egzersizi boyunca bize yol gösterin.


1
Buradaki sohbete bir şey eklemeyebilir, ancak kayıt için bu adımların geliştiğini görmekle gerçekten ilgileneceğimi belirtmek istiyorum. Teşekkürler Matt. Darren Wiens'in sıfırdan bir MXD oluşturması ve düzeni kılavuzlarla doldurmasıyla ilgili bir makale buldum . Ayrıca Mark Cederholm'un snippet modülünün bu çabalarda gerçekten yararlı / sıklıkla kullanıldığı görülüyor .
Jim

Kullanmak için olası bir örnek: gis.stackexchange.com/questions/86007/… (açıklama: Üzerinde çalıştığım sorun, Q'yu sormuş. Beni (iyi hazırlanmış) cevaba yendi, tüm krediyi alın ! ;-)
matt wilkie

Arcobjects girmek zor olabilir, yardım belgeleri tamam ama örnekler daha iyi: En büyük sorunlardan biri, X nesnesine sahip olduğum gibi, bir nesnenin mirasını çözmek, şimdi Y nesnesini nasıl elde ederim ? Visual Studio 2008 veya 2010 express'e (bulabilirseniz ücretsiz indirme) sahip olabilirseniz, SDK'yı yükleyin, yardım belgelerini ve yerel olarak bir sürü örneği alacaksınız.
Michael Stimson

1
@mattwilkie umarım bu sular çok çamurlu değildir ... ama mevcut .NET kodunu python'a taşımak ve tip döküm sözdizimini bulmak için, .NET için python comtypes yaklaşımından biraz daha düz görünüyor . Bununla birlikte, sadece .NET için python keşfettim ve henüz test etmedim.
user2856

1
@mattwilkie az önce python.Net keşfetti ArcGIS SDK yüklü gerektirir (montaj sarıcı dll komut dosyası ile dağıtılmadıkça ...) ArcGIS Desktop ek olarak, bu yüzden comtypes yaklaşımı kadar taşınabilir değil.
user2856

Yanıtlar:


9

Bu alanda da çok güçlü değilim, ancak Snippets modülünü değiştirdim ve çok basit görevler için birkaç paket yaptım. Sadece satır öğeleri eklemek için bir örnek var. Ana bloğun altındaki örnek , belgenin hemen dışındaki mizanpaj görünümüne bir üçgen oluşturur.

Bu komut dosyasını, mizanpajdaki münferit satırlardan ve metin öğelerinden grafik tablolar yapmak için başka bir ve kavisli arama imleçleriyle birlikte kullanıyorum, ancak bu hızla "basit" örnekten uzaklaşıyor. Aşağıdaki kod oldukça basittir ve parçacıkların değiştirilmiş bir sürümünü kullanır:

from snippets import *
def add_line(pApp=None, name='Line', x=None, y=None, end_x=None, end_y=None,
             x_len=0, y_len=0, anchor=0, view='layout'):
    '''adds a line to an ArcMap Document

    Required:
    pApp -- reference to either open ArcMap document or path on disk
    name -- name of line element

    Optional:
    x -- start x coordinate, if none, middle of the extent will be used (data view)
    y -- start y coordinate, if none, middle of the extent will be used (data view)
    end_x -- end x coordinate, if making straight lines use x_len
    end_y -- end y coordinate, if making straight lines use y_len
    x_len -- length of line in east/west direction
    y_len -- length of line in north/south direction
    anchor -- anchor point for line element
    view -- choose view for text element (layout|data)

        Anchor Points:
        esriTopLeftCorner   0   Anchor to the top left corner.
        esriTopMidPoint     1   Anchor to the top mid point.
        esriTopRightCorner  2   Anchor to the top right corner.
        esriLeftMidPoint    3   Anchor to the left mid point.
        esriCenterPoint     4   Anchor to the center point.
        esriRightMidPoint   5   Anchor to the right mid point.
        esriBottomLeftCorner    6   Anchor to the bottom left corner.
        esriBottomMidPoint  7   Anchor to the bottom mid point.
        esriBottomRightCorner   8   Anchor to the botton right corner.
    '''
    GetDesktopModules()
    import comtypes.gen.esriFramework as esriFramework
    import comtypes.gen.esriArcMapUI as esriArcMapUI
    import comtypes.gen.esriSystem as esriSystem
    import comtypes.gen.esriGeometry as esriGeometry
    import comtypes.gen.esriCarto as esriCarto
    import comtypes.gen.esriDisplay as esriDisplay
    import comtypes.gen.stdole as stdole

    # set mxd
    if not pApp:
        pApp = GetApp()
    pDoc = pApp.Document
    pMxDoc = CType(pDoc, esriArcMapUI.IMxDocument)
    pMap = pMxDoc.FocusMap
    pMapL = pMap
    if view.lower() == 'layout':
        pMapL = pMxDoc.PageLayout
    pAV = CType(pMapL, esriCarto.IActiveView)
    pSD = pAV.ScreenDisplay

    # set coords for elment
    pFact = CType(pApp, esriFramework.IObjectFactory)
    if view.lower() == 'data':
        pEnv = pAV.Extent
        if x == None:
            x = (pEnv.XMin + pEnv.XMax) / 2
        if y == None:
            y = (pEnv.YMin + pEnv.YMax) / 2
    else:
        # default layout position, move off page
        if x == None: x = -4
        if y == None: y = 4

    # from point
    pUnk_pt = pFact.Create(CLSID(esriGeometry.Point))
    pPt = CType(pUnk_pt, esriGeometry.IPoint)
    pPt.PutCoords(x, y)

    # to point
    pUnk_pt2 = pFact.Create(CLSID(esriGeometry.Point))
    pPt2 = CType(pUnk_pt2, esriGeometry.IPoint)
    if x_len or y_len:
        pPt2.PutCoords(x + x_len, y + y_len)
    elif end_x or end_y:
        pPt2.PutCoords(end_x, end_y)

    # line (from point - to point)
    pUnk_line = pFact.Create(CLSID(esriGeometry.Polyline))
    pLg = CType(pUnk_line, esriGeometry.IPolyline)
    pLg.FromPoint = pPt
    pLg.ToPoint = pPt2

    # preset color according to RGB values
    pUnk_color = pFact.Create(CLSID(esriDisplay.RgbColor))
    pColor = CType(pUnk_color, esriDisplay.IRgbColor)
    pColor.Red, pColor.Green, pColor.Blue = (0,0,0) #black line

    # set line properties
    pUnk_line = pFact.Create(CLSID(esriDisplay.SimpleLineSymbol))
    pLineSymbol = CType(pUnk_line, esriDisplay.ISimpleLineSymbol)
    pLineSymbol.Color = pColor

    # create the actual element
    pUnk_elm = pFact.Create(CLSID(esriCarto.LineElement))
    pLineElement = CType(pUnk_elm, esriCarto.ILineElement)
    pLineElement.Symbol = pLineSymbol
    pElement = CType(pLineElement, esriCarto.IElement)

    # elm properties
    pElmProp = CType(pElement, esriCarto.IElementProperties3)
    pElmProp.Name = name
    pElmProp.AnchorPoint = esriCarto.esriAnchorPointEnum(anchor)
    pElement.Geometry = pLg

    # add to map
    pGC = CType(pMapL, esriCarto.IGraphicsContainer)
    pGC.AddElement(pElement, 0)
    pGCSel = CType(pMapL, esriCarto.IGraphicsContainerSelect)
    pGCSel.SelectElement(pElement)
    iOpt = esriCarto.esriViewGraphics + \
    esriCarto.esriViewGraphicSelection
    pAV.PartialRefresh(iOpt, None, None)
    return pElement

if __name__ == '__main__':

    # testing (make a triangle)
    add_line(name='hypot', end_x=-2, end_y=2, anchor=3)
    add_line(name='vertLine', y_len=-2, anchor=1)
    add_line(name='bottom', y=2, end_x=-2, end_y=2)

resim açıklamasını buraya girin

Düzenle:

@mehmet_yilmaz

İçe aktarma işlemlerini bulmaya gelince, bu, Arc SD Nesneleri Model Diyagramlarına bakmanız veya .NET SDK yardım belgelerinde belirli bir Sınıf veya Arabirimin hangi ad alanından çağrıldığını görmeniz gereken yerdir. Bazı durumlarda, kalıtım nedeniyle birden fazla ad alanı kullanılabilir.

ArcObjects konusunda uzman değilim, bu yüzden CType () ile bir şeyleri ne zaman yayınlayacağımı anlamak biraz zaman alır. Çoğu, ben çevrimiçi örnekleri aldı. Ayrıca, VB.NET örneklerinin sözdizimi Python'da yaptıklarınıza daha yakın görünüyor, ancak C # örnekleri okunabilirlik açısından bana daha mantıklı geliyor (eğer herhangi bir anlam ifade ediyorsa). Ancak, genel bir kural olarak, genellikle bu adımları izlerim:

  1. Bir nesneyi örneklemek üzere yeni bir COM nesnesi (genellikle bir sınıf) için değişken oluşturma
  2. Yöntemlere ve özelliklere erişime izin vermek üzere COM nesnesini bir arabirime / arabirimlere atamak için CType kullanın. CType ayrıca QueryInterface () üzerinden Comtypes Interface Pointer'ı döndürecektir. İşaretçi döndükten sonra özellikleri ve yöntemleri ile etkileşime girebilirsiniz.

Ben doğru terminoloji kullanıyorum ya da değil emin değilim ... Ben öncelikle bazı ArcObjects "dabbles" bir Python geliştirici ... Ben sadece buzdağının ucuna dokundum.

Ayrıca, bu yardımcı işlev tüm ArcObjects Nesne Kitaplıklarını (.olb) yükler:

def load_all():
    '''loads all object libraries'''
    from comtypes.client import GetModule
    mods = glob.glob(os.path.join(GetLibPath(), '*.olb'))
    for mod in mods:
        GetModule(mod)
    return


def GetLibPath():
    '''Reference to com directory which houses ArcObjects
    Ojbect Libraries (*.OLB)'''
    return glob.glob(os.path.join(arcpy.GetInstallInfo()['InstallDir'], 'com'))[0]

yararlı örnek için teşekkürler! Q'nun itme gücü, belirli görev tariflerinde daha az (olması gerektiği gibi) ve kişinin ilk olarak tarifi oluşturmak için bilgiyi nasıl alıp yazdığı hakkında daha fazladır. Örneğin, bunu nasıl bildiniz import comtypes.gen.esriArcMapUI as esriArcMapUIve daha sonra nasıl kullandınız pMxDoc = CType(pDoc, esriArcMapUI.IMxDocument)(ve bu ifadedeki sözdizimini ortaya çıkardınız )?
matt wilkie

Sorularınızı cevaplamaya çalışmak için orijinal cevabımı düzenledim. Birkaç başka örneğim de var, ancak yukarıdaki snippet muhtemelen en okunabilir.
crmackey

Ayrıca, bu kitabı geçen yıl satın aldım: amazon.com/Beginning-ArcGIS-Desktop-Development-using/dp/…
crmackey

7

Başka bir, ilgili ama biraz farklı, post Ben Esri ArcObjects yardım belgeleri etrafında başlarını sarmaya çalışan python kullanıcıları için ilgi olabilir bir cevap sağladı ..

Diğer taraftan geldim: Python'u bile duymadan önce ArcObjects'i uzun (çok uzun) biliyordum ve bu tür mesajlar sayesinde python'un kolay komut dosyasında bazı kritik ArcObjects'i ekleyebiliyorum ( örnek için bu gönderiye bakın) ). Miras, yöntem ve özellikleri anlamaya çalışmanın hayal kırıklığını hatırlıyorum; Y ile ilgili olan X'im var gibi ikilemler ... Peki X'den Y.Method () 'a nasıl ulaşabilirim?

Cevap, arabirimi uygulayan CoClasses'a bakmaktır ( burada tam metne bakın ) .. Temel bir örnek için, bir katmanın bir tanım sorgusu olup olmadığını görmek istiyorsanız ve eğer öyleyse:

C # dilinde:

ILayer pLayer = pMap.get_Layer(LayerIndex);
IFeatureLayer pFtLayer = pLayer as IFeatureLayer; // also written pFtLayer = (IFeatureLayer) pLayer
IFeatureLayerDefinition pFtLayDef = (IFeatureLayerDefinition)pFtLayer; // also works as pFtLayDef = pFtLayer as IFeatureLayerDefinition;
if (pFtLayDef.DefinitionExpression.Length == 0)
    Console.WriteLine("No definition query");
else
    Console.WriteLine("Query is " + pFtLayDef.DefinitionExpression);

Bunun yerine ctype, C # kullanımları (VB belirgin olan) ()veya asdöküm, örneğin IObject x = (IObject)y;aynı (temelde) olan IObject x = y as IObject;olacağını dim x as IObject = ctype(y,IObject)VB.

IFeatureLayerDefinition için almak için bir IFeatureLayer gerektiğini söyleyebilirim çünkü: resim açıklamasını buraya girin

IFeatureLayer için yardım belgesini okuduğunuzda şunları görürsünüz: resim açıklamasını buraya girin

Bu, ILayer'ın FeatureLayer (veya diğer CoClasses'lardan herhangi biri) türünde olması koşuluyla, ILayer-> IFeatureLayer-> IFeatureLayerDef'e gitmenin güvenli olduğunu gösterir.

Peki ben ve hayır ben neyin var? I arayüzü demek, bir CoClass (bir tür ) olmadan işi yapan bit , bu yüzden gerçekten kullanmak istediğiniz her şey bir I ile başlamalı ve yeni bir tane oluşturuyorsanız veya türü kontrol ediyorsanız Bir arabirimin birçok CoClasses'u olabilir ve bir CoClass birçok arabirimi destekleyebilir, ancak aslında işi yapan arabirimdir .

Python'da:

# I'm assuming arcpy is already imported and comtypes installed
from comtypes.client import GetModule, CreateObject
mC = GetModule(r'C:\Your path\Desktop10.1\com\esriCarto.olb')
mU = GetModule(r'C:\Your path\Desktop10.1\com\esriArcMapUI.olb')
mF = GetModule(r"C:\Your path\Desktop10.1\com\esriFramework.olb")

import comtypes.gen.esriCarto as esriCarto
import comtypes.gen.esriFramework as esriFramework
import comtypes.gen.esriArcMapUI as esriArcMapUI

app = CreateObject(mF.AppROT, interface=mF.IAppROT) # a reference to the ArcMap application
pDoc = ctype(app.Item(0).Document,mU.IMxDocument)   # a reference to the current document
pMap = pDoc.FocusMap # the currently active map
pLayer = pMap.get_layer(LayerIndex)
pFtLayer = ctype(pLayer,esriCarto.IFeatureLayer)
pFtLayDef = ctype(pFtLayer,esriCarto.IFeatureLayerDefinition)
if len(pFtLayDef.DefinitionExpression) == 0:
    print("No definition expression")
else:
    print("Query is " + pFtLayDef.DefinitionExpression)

Bu örnek, yalnızca python penceresinde veya bir eklentide kullanılabilen geçerli uygulamaya giden yolu bulduğu için C'den biraz daha fazlasını yapar, bunu komut satırından çalıştırmayı denerseniz uygulama Null olur ve komut dosyası null başvuru istisnasıyla kilitlenme.


Vay be, bunu gönderdiğin için çok teşekkür ederim! ArcObject Diyagramlarını anlamak için bazı zorluklar yaşadım. Çitin diğer tarafından gelen (.NET ArcObjects deneyiminin birçoğu) kendiniz gibi birinden bazı girişler yapmak güzel. Bazı zorluklarla karşılaştığım bir şey, özellik veri kümesinde bulunan bir özellik sınıfına comtypes ve python aracılığıyla erişmek. Geçmişte önce özellik veri kümesi ve daha sonra özellik sınıfı açmayı denedim ama herhangi bir şans (bazı boş işaretçiler alma) yoktu düşünüyorum. Bunun için herhangi bir python örneğiniz var mı?
crmackey

1
Çok fazla değil, gerçekten sadece python'da comtypes ile başlıyorum, ancak bir çalışma alanı (IFeatueWorkspace) nesnesinden bir özellik sınıfını açmak için sadece adı kullanın, özellik veri kümesini hiç dahil etmeyin - önemli değil bir özellik veri kümesinde, tüm adlar benzersizdir ... bkz. help.arcgis.com/tr/sdk/10.0/arcobjects_net/componenthelp/… Bazı kodlarla yeni bir soru açabilir misiniz ve bir göz atacağım . Özellik veri kümesi, veri kümelerinin yinelemesiyle (IFeatureDataset.Subsets) kullanılabilir, ancak yalnızca adla açmak daha temizdir.
Michael Stimson

1
Teşekkürler @Michael Miles-Stimson. Başka bir şans vereceğim. Anlayamıyorsam, mevcut kodumla yeni bir soru göndereceğim.
crmackey

@MichaelStimson Comytpes kullanarak python'da arcobjects kullanabileceğimi anlıyorum. Asla arcobjects kullanmadım. Comtypes ve arcpy kullanarak ağ veri kümesi oluşturmak gibi görevleri gerçekleştirmek için hiçbir yerde örnek olmadığı göz önüne alındığında, comtypes kullanmadan önce arcobjects'i anlamam gerekir mi? Yoksa arkpy ve comtypes kullanmak için sadece kendi başlarına comty'ler öğrenebilir miyim?
ketar

1
@ketar, python'da kullanmaya çalışmadan önce ArcObjects hakkında biraz bilgi sahibi olmak iyi bir fikirdir. Python'da çok sayıda ArcObjects örneği olmasa da (henüz) ArcObjects'te , ağ veri kümeleri için resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/… gibi yardımcı örnekler bulunmaktadır (derleme, ağ veri kümeleri için son öğedir. sayfa). ArcObjects kodu python'dan (arcpy) önemli ölçüde daha ayrıntılıdır; Şahsen ben VB veya C # kodlamak ve sonra sonuçları ile mutlu zaman kopyala / python yapıştırın.
Michael Stimson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.