नए गैर-अतिव्यापी बहुभुज में अतिव्यापी विस्फोट?


10

कई बहुभुजों को देखते हुए, जो कई तरीकों से ओवरलैप करते हैं, मैं इन विशेषताओं से निर्यात करना चाहता हूं सभी बहुभुज जो दूसरों के साथ ओवरलैप नहीं करते हैं, पुनरावृत्त।

यह उत्पाद बिना किसी अतिव्यापी के कई विशेषताएं होंगी, जो एक साथ सम्‍मिलित होने पर मूल बनाते हैं।

तब उत्पादों को आंचलिक सांख्यिकी के इनपुट के रूप में इस्तेमाल किया जा सकता था, और यह प्रत्येक बहुभुज पर आंचलिक सांख्यिकी को पुनरावृत्त करने की तुलना में बहुत तेज़ होगा।

मैं सफलता के बिना ArcPy में इसे कोड करने की कोशिश कर रहा हूं।

क्या ऐसा करने के लिए कोड पहले से मौजूद है?


क्या आपका मतलब है कि आप डेटा को एक स्थैतिक रूप से सही सेट में 'समतल' करना चाहते हैं?
nagytech

@ जिओस्टनल जोनलस्टैट्स को ऐसे पॉलीगनों की आवश्यकता होती है जो ओवरलैप नहीं करते हैं। जब आपके पास एक अतिव्यापी संग्रह होता है, तो स्पष्ट लेकिन अकुशल समाधान पोल पर लूप करना और एक-एक करके जोनल स्टैटस की गणना करना होता है। गैर-अतिव्यापी ध्रुवों के एक सबसेट का चयन करना अधिक कुशल होगा, जोनलस्टेट्स को उन पर लागू करें, और पुनरावृति। प्रश्न पूछता है कि इस तरह के चयन को कुशलतापूर्वक कैसे किया जाए।
whuber

व्हीबर - मुझे लगता है कि @Geoist इनपुट बहुभुज के चौराहों से गैर-अतिव्यापी पॉलीगनों का एक सेट बनाने का सुझाव दे रहा है। इस छवि को देखें - (टिप्पणियों में चित्र पोस्ट नहीं कर सकते?)। इनपुट बाईं ओर है। पूरे क्षेत्र को तीन बहुभुजों द्वारा कवर किया गया है, जिनमें से प्रत्येक अन्य दोनों को काटता है। केवल गैर-अतिव्यापी उपसमुच्चय एकल होते हैं और ये गोतनुकी की आवश्यकता को पूरा नहीं करते हैं जो संघ अंतरिक्ष को भरता है। मुझे लगता है कि जियोनिस्ट सही पर गैर-अन्तर्विभाजक क्षेत्रों का सेट बनाने का सुझाव दे रहा है जो कि जोनलस्टैट्स के लिए मान्य है
Llaves

मुझे लगता है कि कुछ भ्रम है कि अंतिम उत्पाद क्या होना चाहिए। क्या आप एक उदाहरण प्रदान कर सकते हैं? मेरी व्याख्या यह है कि आप पॉलीगनों के चयन के लिए आउटपुट चाहते हैं जो ओवरलैप नहीं करते हैं - शेष पॉलीफोन को त्यागने या भंग करने के दौरान। क्या आप एक या कई फीचर कक्षाओं के साथ काम कर रहे हैं?
एरोन

1
मेरे लिए ध्वनि की तरह @gotanuki जो उसमें केवल सुविधा कक्षाओं की न्यूनतम संख्या बनाने के लिए इच्छुक है गैर-अतिव्यापी ओवरलैपिंग बहुभुज के साथ एक बहुभुज विशेषता वर्ग से बहुभुज
PolyGeo

जवाबों:


14

यह एक ग्राफ़िक्स रंग समस्या है

याद रखें कि एक ग्राफ रंग एक ग्राफ के कोने को इस तरह से रंग का एक असाइनमेंट है कि कोई भी दो कोने जो एक किनारे को साझा करते हैं, उनका रंग भी समान होगा। विशेष रूप से, ग्राफ का (अमूर्त) कोने बहुभुज हैं। जब भी वे (बहुभुज) को काटते हैं, तो दो कोने एक (अप्रत्यक्ष) किनारे से जुड़े होते हैं। यदि हम समस्या का कोई हल निकालते हैं - जो कि पॉलीगन्स के संग्रह को कहना ( k ) का एक क्रम है - और अनुक्रम में प्रत्येक संग्रह के लिए एक अनूठा रंग प्रदान करता है, तो हमें ग्राफ का k -coloring प्राप्त होगा । एक छोटे से कश्मीर को खोजने के लिए यह वांछनीय है ।

यह समस्या बहुत कठिन है और मनमाने रेखांकन के लिए अनसुलझी बनी हुई है। एक अनुमानित समाधान पर विचार करें जो कोड के लिए सरल है। एक अनुक्रमिक एल्गोरिथ्म करना चाहिए। वेल्श-पॉवेल एल्गोरिथ्म एक लालची समाधान है जो डिग्री द्वारा वर्टीकल के अवरोही क्रम पर आधारित है। मूल बहुभुज की भाषा में अनुवादित, पहले बहुभुज को दूसरे बहुभुजों की संख्या के अवरोही क्रम में क्रमबद्ध करते हैं, जिन्हें वे ओवरलैप करते हैं। क्रम में काम करते हुए, पहले बहुभुज को एक प्रारंभिक रंग दें। प्रत्येक क्रमिक चरण में, मौजूदा बहुभुज को मौजूदा रंग से रंगने का प्रयास करें: यानी ऐसा रंग चुनें जो न होपहले से ही किसी भी बहुभुज के पड़ोसियों द्वारा उपयोग किया जाता है। (उपलब्ध रंगों में से चुनने के कई तरीके हैं, या तो एक का उपयोग करें जो कम से कम इस्तेमाल किया गया है या एक यादृच्छिक रूप से चुनें।) यदि अगला बहुभुज एक मौजूदा रंग के साथ रंगीन नहीं हो सकता है, तो एक नया रंग बनाएं और उसी के साथ इसे रंग दें।

एक बार जब आप रंगों की एक छोटी संख्या के साथ एक रंग प्राप्त कर लेते हैं, तो रंग द्वारा आंचलिक रंग का प्रदर्शन करें: निर्माण द्वारा, आपको गारंटी दी जाती है कि दिए गए रंग ओवरलैप के कोई दो बहुभुज नहीं हैं।


इसमें नमूना कोड है R। (पायथन कोड बहुत अलग नहीं होगा।) सबसे पहले, हम दिखाए गए सात बहुभुजों में से ओवरलैप का वर्णन करते हैं।

सात बहुभुजों का नक्शा

edges <- matrix(c(1,2, 2,3, 3,4, 4,5, 5,1, 2,6, 4,6, 4,7, 5,7, 1,7), ncol=2, byrow=TRUE)

यही है, बहुभुज 1 और 2 ओवरलैप करते हैं, और इसलिए बहुभुज 2 और 3, 3 और 4, ..., 1 और 7 करते हैं।

अवरोही डिग्री के आधार पर छंटनी करें:

vertices <- unique(as.vector(edges))
neighbors <- function(i) union(edges[edges[, 1]==i,2], edges[edges[, 2]==i,1])
nbrhoods <- sapply(vertices, neighbors)
degrees <- sapply(nbrhoods, length)
v <- vertices[rev(order(degrees))]

ए (क्रूड) अनुक्रमिक रंग एल्गोरिथ्म जल्द से जल्द उपलब्ध रंग का उपयोग करता है जो पहले से ही किसी अतिव्यापी बहुभुज द्वारा उपयोग नहीं किया जाता है:

color <- function(i) {
  n <- neighbors(i)
  candidate <- min(setdiff(1:color.next, colors[n]))
  if (candidate==color.next) color.next <<- color.next+1
  colors[i] <<- candidate
}

डेटा संरचनाओं को प्रारंभ करें ( colorsऔर color.next) और एल्गोरिथ्म लागू करें:

colors <- rep(0, length(vertices))
color.next <- 1
temp <- sapply(v, color)

बहुभुज को रंगों के अनुसार समूहों में विभाजित करें:

split(vertices, colors)

इस उदाहरण में आउटपुट चार रंगों का उपयोग करता है:

$`1`
[1] 2 4

$`2`
[1] 3 6 7

$`3`
[1] 5

$`4`
[1] 1

बहुभुज के चार रंग

इसने बहुभुज को चार गैर-अतिव्यापी समूहों में विभाजित किया है। इस मामले में समाधान इष्टतम नहीं है ({{3,6,5}, {2,4}, {1,7}} इस ग्राफ के लिए एक तीन रंग है)। सामान्य तौर पर इसका समाधान बहुत बुरा नहीं होना चाहिए, हालांकि।


मुझे यकीन नहीं है कि यह सवाल का जवाब देता है, या सवाल क्या है, लेकिन यह एक अच्छा जवाब है कोई भी कम नहीं है।
नगीटेक

@Geoist क्या कोई तरीका है जिससे मैं दृष्टांत को स्पष्ट कर सकता हूँ या समस्या को बेहतर तरीके से समझा सकता हूँ?
whuber

6

# वाउचर द्वारा सुझाई गई कार्यप्रणाली ने मुझे एक नई दिशा लेने के लिए प्रेरित किया, और यहां मेरा आर्कटिक समाधान है, दो कार्यों में। पहले कहा जाता है, countOverlaps, दो फ़ील्ड बनाते हैं, प्रत्येक पाली के लिए रिकॉर्ड करने के लिए "ओवरलैप्स" और "ओवलपक्वांट" बनाते हैं, जो इसके साथ ओवरलैप किए गए पोल और कितने ओवरलैप हुए। दूसरा फ़ंक्शन, explodeOverlaps, एक तीसरा फ़ील्ड बनाता है, "एक्सप्लोर", जो गैर-अतिव्यापी पॉलिस के प्रत्येक समूह को एक अद्वितीय पूर्णांक देता है। उपयोगकर्ता इस क्षेत्र के आधार पर नए fc निर्यात कर सकता है। प्रक्रिया दो कार्यों में टूटी हुई है क्योंकि मुझे लगता है कि countOverlaps टूल अपने आप उपयोगी साबित हो सकता है। कृपया कोड की ढिलाई (और लापरवाह नामकरण सम्मेलन) का बहाना करें, क्योंकि यह बहुत प्रारंभिक है, लेकिन यह काम करता है। यह भी सुनिश्चित करें कि "idName" फ़ील्ड विशिष्ट आईडी के साथ एक फ़ील्ड का प्रतिनिधित्व करता है (केवल पूर्णांक आईडी के साथ परीक्षण किया गया)। इस समस्या से निपटने के लिए आवश्यक रूपरेखा प्रदान करने के लिए धन्यवाद!

def countOverlaps(fc,idName):
    intersect = arcpy.Intersect_analysis(fc,'intersect')
    findID = arcpy.FindIdentical_management(intersect,"explFindID","Shape")
    arcpy.MakeFeatureLayer_management(intersect,"intlyr")
    arcpy.AddJoin_management("intlyr",arcpy.Describe("intlyr").OIDfieldName,findID,"IN_FID","KEEP_ALL")
    segIDs = {}
    featseqName = "explFindID.FEAT_SEQ"
    idNewName = "intersect."+idName

    for row in arcpy.SearchCursor("intlyr"):
        idVal = row.getValue(idNewName)
        featseqVal = row.getValue(featseqName)
        segIDs[featseqVal] = []
    for row in arcpy.SearchCursor("intlyr"):
        idVal = row.getValue(idNewName)
        featseqVal = row.getValue(featseqName)
        segIDs[featseqVal].append(idVal)

    segIDs2 = {}
    for row in arcpy.SearchCursor("intlyr"):
        idVal = row.getValue(idNewName)
        segIDs2[idVal] = []

    for x,y in segIDs.iteritems():
        for segID in y:
            segIDs2[segID].extend([k for k in y if k != segID])

    for x,y in segIDs2.iteritems():
        segIDs2[x] = list(set(y))

    arcpy.RemoveJoin_management("intlyr",arcpy.Describe(findID).name)

    if 'overlaps' not in [k.name for k in arcpy.ListFields(fc)]:
        arcpy.AddField_management(fc,'overlaps',"TEXT")
    if 'ovlpCount' not in [k.name for k in arcpy.ListFields(fc)]:
        arcpy.AddField_management(fc,'ovlpCount',"SHORT")

    urows = arcpy.UpdateCursor(fc)
    for urow in urows:
        idVal = urow.getValue(idName)
        if segIDs2.get(idVal):
            urow.overlaps = str(segIDs2[idVal]).strip('[]')
            urow.ovlpCount = len(segIDs2[idVal])
        urows.updateRow(urow)

def explodeOverlaps(fc,idName):

    countOverlaps(fc,idName)

    arcpy.AddField_management(fc,'expl',"SHORT")

    urows = arcpy.UpdateCursor(fc,'"overlaps" IS NULL')
    for urow in urows:
        urow.expl = 1
        urows.updateRow(urow)

    i=1
    lyr = arcpy.MakeFeatureLayer_management(fc)
    while int(arcpy.GetCount_management(arcpy.SelectLayerByAttribute_management(lyr,"NEW_SELECTION",'"expl" IS NULL')).getOutput(0)) > 0:
        ovList=[]
        urows = arcpy.UpdateCursor(fc,'"expl" IS NULL','','','ovlpCount D')
        for urow in urows:
            ovVal = urow.overlaps
            idVal = urow.getValue(idName)
            intList = ovVal.replace(' ','').split(',')
            for x in intList:
                intList[intList.index(x)] = int(x)
            if idVal not in ovList:
                urow.expl = i
            urows.updateRow(urow)
            ovList.extend(intList)
        i+=1

2
इसे मेरे समाधान से जोड़ने के लिए: आपका मेरे कोड में countOverlapsदो पंक्तियों से मेल खाता है nbrhoods <- sapply(vertices, neighbors); degrees <- sapply(nbrhoods, length): degreesओवरलैप काउंट है। बेशक आपका कोड लंबा है, क्योंकि यह अधिकांश जीआईएस विश्लेषण को दर्शाता है जो मेरे समाधान में दी गई है: अर्थात्, कि आप पहली बार पहचानते हैं कि कौन से बहुभुज ओवरलैप करते हैं, और अंत में आप समाधान का उपयोग बहुभुज डेटासेट के लिए करते हैं। यह एक अच्छा विचार ग्राफ-सैद्धांतिक गणना संपुटित होगा इसलिए यदि आप कभी भी एक बेहतर रंग एल्गोरिथ्म लगता है, यह आसान में प्लग करने के लिए किया जाएगा।
whuber

1

थोड़ी देर हो गई है, लेकिन मैंने इस कोड का उपयोग अपने आवेदन के लिए किया है और यह बहुत अच्छा काम कर रहा है - धन्यवाद। मैंने इसे अपडेट करने के लिए इसे फिर से लिखा, इसे लाइनों पर लागू करें (एक सहिष्णुता के साथ) और इसे काफी तेज करें (नीचे - मैं इसे 50 मिलियन प्रतिच्छेदन बफ़र्स पर चला रहा हूं और इसमें केवल कुछ घंटे लगते हैं)।

def ExplodeOverlappingLines(fc, tolerance, keep=True):
        print('Buffering lines...')
        idName = "ORIG_FID"
        fcbuf = arcpy.Buffer_analysis(fc, fc+'buf', tolerance, line_side='FULL', line_end_type='FLAT')
        print('Intersecting buffers...')
        intersect = arcpy.Intersect_analysis(fcbuf,'intersect')

        print('Creating dictionary of overlaps...')
        #Find identical shapes and put them together in a dictionary, unique shapes will only have one value
        segIDs = defaultdict(list)
        with arcpy.da.SearchCursor(intersect, ['Shape@WKT', idName]) as cursor:
            x=0
            for row in cursor:
                if x%100000 == 0:
                    print('Processed {} records for duplicate shapes...'.format(x))
                segIDs[row[0]].append(row[1])
                x+=1

        #Build dictionary of all buffers overlapping each buffer
        segIDs2 = defaultdict(list)
        for v in segIDs.values():
            for segID in v:
                segIDs2[segID].extend([k for k in v if k != segID and k not in segIDs2[segID]])

        print('Assigning lines to non-overlapping sets...')
        grpdict = {}
        # Mark all non-overlapping one to group 1
        for row in arcpy.da.SearchCursor(fcbuf, [idName]):
            if row[0] in segIDs2:
                grpdict[row[0]] = None
            else:
                grpdict[row[0]] = 1

        segIDs2sort = sorted(segIDs2.items(), key=lambda x: (len(x[1]), x[0])) #Sort dictionary by number of overlapping features then by keys
        i = 2
        while None in grpdict.values(): #As long as there remain features not assigned to a group
            print(i)
            ovset = set()  # list of all features overlapping features within current group
            s_update = ovset.update
            for rec in segIDs2sort:
                if grpdict[rec[0]] is None: #If feature has not been assigned a group
                    if rec[0] not in ovset: #If does not overlap with a feature in that group
                        grpdict[rec[0]] = i  # Assign current group to feature
                        s_update(rec[1])  # Add all overlapping feature to ovList
            i += 1 #Iterate to the next group

        print('Writing out results to "expl" field in...'.format(fc))
        arcpy.AddField_management(fc, 'expl', "SHORT")
        with arcpy.da.UpdateCursor(fc,
                                   [arcpy.Describe(fc).OIDfieldName, 'expl']) as cursor:
            for row in cursor:
                if row[0] in grpdict:
                    row[1] = grpdict[row[0]]
                    cursor.updateRow(row)

        if keep == False:
            print('Deleting intermediate outputs...')
            for fc in ['intersect', "explFindID"]:
                arcpy.Delete_management(fc)

-3

इस मामले में मैं आम तौर पर निम्नलिखित विधि का उपयोग करता हूं:

  • एक UNION के माध्यम से फ़ीचर वर्ग पास करें; (यह अपने सभी चौराहों में बहुभुजों को तोड़ता है)
  • एक्स, वाई और क्षेत्र फ़ील्ड जोड़ें और उनकी गणना करें;
  • X, Y, एरिया फ़ील्ड द्वारा परिणाम को भंग करें।

मेरा मानना ​​है कि परिणाम वही होगा जो आप चाहते थे, और आप ओवरलैप की संख्या भी गिन सकते हैं। पता नहीं कि प्रदर्शन के मामले में यह आपके लिए बेहतर होगा या नहीं।


2
यह विधि आपको वांछित उत्पाद के लिए नहीं मिलती है, जो चयन की एक न्यूनतम श्रृंखला या मूल के अद्वितीय फीचर वर्ग हैं जो ओवरलैप नहीं करते हैं। उत्पादों को आंचलिक आँकड़ों में खिलाया जाएगा, और इसलिए प्रत्येक सुविधा की मूल ज्यामिति को बनाए रखना महत्वपूर्ण है।
ndimhypervol

आप सही हैं, क्षमा करें। मुझे सवाल अच्छे से समझ नहीं आया। उस मामले में, और रेखापुंज के आकार के आधार पर, मैं सामान्य रूप से रेखापुंज को एक अस्थायी बिंदु सुविधा वर्ग (प्रत्येक कोशिका एक बिंदु) में परिवर्तित करूंगा, और इसके और बहुभुज परत के बीच एक स्थानिक जुड़ाव करूंगा। हो सकता है कि इसका एक बहुत ही सरल, और प्रदर्शन अमित्र दृष्टिकोण है, लेकिन काम करता है और अतिव्याप्त बहुभुज आपको कोई समस्या नहीं देंगे।
अलेक्जेंड्रे नेटो

यदि मैं सही ढंग से समझता हूं कि इस स्थानिक जुड़ाव से आपका क्या मतलब है, तो आपका दूसरा समाधान अभी भी काम नहीं करेगा, अलेक्जेंड्रे, क्योंकि अंकों और बहुभुजों के बीच कई-से-कई संबंध हैं। भले ही, किसी भी बड़े आकार के रेखापुंज के लिए यह वेक्टर-आधारित दृष्टिकोण बेहद अक्षम होगा और बड़ी आपदाओं के लिए इसे अंजाम देना असंभव होगा।
व्हिबर

@ जब आप एक बहुत धीमी प्रक्रिया के बारे में सही हैं (एक 4284 x 3009 रेखापुंज और 2401 polygons के साथ आधे घंटे के आसपास मुझे टोके, डुअलकोर 2.8Ghz में, विस्टा के साथ 3Gb रैम)। लेकिन यह काम करता है, जैसा कि मैंने पहले ही इसका परीक्षण किया है। स्थानिक जुड़ाव में आपको एक से एक संबंधों का उपयोग करना होगा, और रेखापुंज मानों (जैसे कि, सम, आदि ...) को एकत्रित करना होगा। परिणाम मूल के समान एक वेक्टर बहुभुज परत होगा लेकिन प्रत्येक बहुभुज को प्रतिच्छेद करने वाले कुलीन रेखापुंज मानों के साथ एक नए स्तंभ के साथ। एक इष्टतम समाधान नहीं होने से यह कम प्रोग्रामिंग कौशल वाले किसी व्यक्ति के लिए उपयोगी हो सकता है (जैसे मुझे :-))।
अलेक्जेंड्रे नेटो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.