Viac

Nie je možné správne iterovať IFeatureCursor (volanie ArcObjects z Pythonu)

Nie je možné správne iterovať IFeatureCursor (volanie ArcObjects z Pythonu)


Nedávno som začal používať niektoré z ArcObjects vo svojich moduloch Python. Vďaka všetkým užitočným príspevkom a postrehom, ktoré zdieľali @matt wilkie a spol., Som mohol začať celkom rýchlo (inštalácia kométov pomocou pipu a stiahnutie útržku 10.2 od Pierssen a zmena „10,2“ na „10,3“ všade).

Snažím sa opakovaťKurzor IFeaturea získate všetky funkcie v rámci triedy funkcií. Vracia sa mi však iba najnovšia funkcia (s najvyššou hodnotou ObjectID).

V triede funkcií je teda 6 funkciíxrange (6)aby to bolo jednoduché.

from comtypes.client import GetModule, CreateObject from snippets102 import GetStandaloneModules, InitStandalone # First through through, need to import the “StandaloneModules”. Môžete komentovať neskôr. #GetStandaloneModules () InitStandalone () def iterate_features (): # Získajte modul GDB esriGeodatabase = GetModule (r "C:  Program Files (x86)  ArcGIS  Desktop10.3  com  esriGeoDatabase.olb") esriDataSourcesGDB "C:  Program Files (x86)  ArcGIS  Desktop10.3  com  esriDataSourcesGDB.olb") # Vytvorte ukazovateľ geodatabázy súboru file_gdb_pointer = CreateObject (progid = esriDataSourcesGDB.FileGDBWorkspaceFactory, interface = esriGeoddbase_World (r "C:  GIS  arcobjects  MyData.gdb", hWnd = 0) #access obsah vnútri gdb feature_workspace = file_gdb.QueryInterface (esriGeodatabase.IFeatureWorkspace) in_fc = feature_workspace.OpenFeatureClass ("Warehouses") "" "vracia ukazovatele na objekty IFeature v rámci triedy funkcií" "" cur = in_fc.Search (None, True) pre i v xrange (6): feature_obj = yield cur.NextFeature () feats = [feat for feat in enum_features (in_fc )] vytlačiť [f.OID pre f in feats] iterate_features ()

Čiaravytlačiť [f.OID for f in feats]vracia[6, 6, 6, 6, 6, 6].

Čo robím zle? Rovnaká logika s generátorom/výnosom (def enum_features ()) funguje dobre pri iterácii tried funkcií v rámci množiny údajov funkcií.

feats_OIDs = [feat.OID pre výkon v enum_features (in_fc)]poskytne správne výsledky,[1, 2, 3, 4, 5, 6], bez toho, aby som robil akékoľvek zmeny v kóde. Zdá sa, že problém je v tom, že keď vytvorím zoznam funkcií[výkon za výkon v enum_features (in_fc)], všetky odkazujú na rovnakú funkciu (pretože keď neskôr preskúmam každú z nich, každá z nich má rovnaké OID).


Myslím si, že lepším prístupom by bolo najskôr zistiť početFeatureCount ()metódaIFeatureClassRozhranie. Toto fungovalo pre mňa:

import arcobjects # moja kópia úryvkov z comtypes.client import CreateObject import os pars = r'C:  TEMP  frontage_test.gdb  parcels 'fc = arcobjects.OpenFeatureClass (*os.path.split (pars)) def enum_features (fc ): import comtypes.gen.esriGeoDatabase ako esriGeoDatabase qf = CreateObject (progid = esriGeoDatabase.QueryFilter, interface = esriGeoDatabase.IQueryFilter) #môžete použiť NewObj aj tu, ak ho máte vo svojich úryvkoch počet = fc.F . Hľadať (qf, True) pre i v xrange (počet): výťažok cur.NextFeature () pre ft v enum_features (fc): tlač ft.OID

A z môjhoarcobjectsmodul, toto je moja funkcia OpenFeatureClass ():

def OpenFeatureClass (sFileGDB, sFCName): InitStandalone () import comtypes.gen.esriGeoDatabase ako esriGeoDatabase dovozné comtypes.gen.esriDataSourcesGDB ako esriDataSourcesGDB pWSF = NewObj (esriDataSourcesGDB.FileGDBWorkspaceFactory,  esriGeoDatabase.IWorkspaceFactory2) PWS = pWSF.OpenFromFile (sFileGDB, 0) pFWS = CType (pWS, esriGeoDatabase.IFeatureWorkspace) # určiť, či existuje FC pred pokusom o otvorenie # http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeoDatabase/IWorkspace2_NameExists.hty # 5 = typ triedy dát (pWS, esriGeoDatabase.IWorkspace2) if pWS2.NameExists (5, sFCName): pFC = pFWS.OpenFeatureClass (sFCName) else: pFC = None print '** % s not found' % sFCName return pFC

UPRAVIŤ

@Alex Tereshenkov položil otázku, ako to zaradiť do zoznamu ukazovateľovIFeatureobjektov, a to je možné vykonať s porozumením zoznamu. Odpoveď je teda áno.

>>> features = [ft for ft in enum_features (fc)] >>> features [: 5] # many of features, so lets just show the first few [, , , , ] >>>

ÚPRAVA 2:

Problém som našiel. V skutočnosti nechceme recyklovať riadky. Keď som to zmenil na falošné, môžeme každého dostať vonIFeaturedo zoznamu.

cur = fc.Hľadať (žiadne, nepravdivé) #nerecyklujte tento objekt IFeature!

Takže teraz, keď to urobíte, mali by ste získať objekt pre každý riadok:

features = [ft for ft in enum_features (fc)] print [ft.OID for ft in features [: 5]]

Je to uvedené v dokumentoch pomoci:

Parameter Recyklácia riadi správanie alokácie objektov riadka. Recyklačné kurzory rehydratujú jeden objekt objektu pri každom načítaní a dajú sa použiť na optimalizáciu prístupu iba na čítanie, napríklad pri kreslení. Je nezákonné udržiavať referenciu na objekt funkcie vrátený recyklačným kurzorom pri viacerých hovoroch na NextFeature na kurzore. Funkcie vrátené recyklačným kurzorom by sa nemali upravovať. Nerecyklačné kurzory vracajú pri každom načítaní samostatný objekt funkcie. Funkcie vrátené nerecyklačným kurzorom je možné upravovať a ukladať s polymorfným správaním.

Geodatabáza zaručuje „sémantiku jedinečných inštancií“ pre objekty nerecyklačných prvkov načítané počas relácie úprav. Inými slovami, ak funkcia získaná vyhľadávacím kurzorom už bola vytvorená a volajúca aplikácia na ňu odkazuje, vráti sa odkaz na existujúci objekt funkcie.

Kurzory nerecyklačných funkcií vrátené z metódy Hľadať MUSIEŤ použiť pri kopírovaní funkcií z kurzora do vkladacieho kurzora inej triedy. Dôvodom je, že recyklačný kurzor znova používa rovnakú geometriu a za určitých okolností môžu mať všetky prvky vložené do vkladacieho kurzora rovnakú geometriu. Použitie nerecyklačného kurzora zaručuje, že každá geometria je jedinečná.


Pozri si video: ArcGIS Tutorial: Sequentially update your attribute table with python