ArcGIS डेस्कटॉप और पायथन का उपयोग करके दो फीचर कक्षाओं में सुविधाओं को परस्पर जोड़ने के बीच कोण ज्ञात करना? [बन्द है]


19

मेरे पास दो इंटरसेक्टिंग लाइन फीचरक्लासेस हैं। मैं ArcGIS 10 और पायथन का उपयोग करके चौराहे के प्रत्येक बिंदु पर कोण खोजना चाहता हूं।

क्या कोई मदद कर सकता है?


मैंने आर्कटिक का उपयोग करते हुए अजगर की स्क्रिप्ट में व्हीबर की विधि (आपको धन्यवाद) दोहराई है लेकिन मुझे कोण गणना के साथ समस्या हो रही है। जब Esri ArcMap (क्षेत्र कैलकुलेटर) के भीतर पूरा किया जाता है तो यह सही ढंग से गणना करता है। जब एक अजगर लिपि के भीतर गणना की जाती है (फिर क्षेत्र कैलकुलेटर का उपयोग करके) यह गलत तरीके से गणना करता है (एक दशमलव के रूप में)। यह केवल रेडियन से डिग्री की समस्या के लिए रूपांतरण नहीं है। कोण के रूप में क्षेत्र की गणना करने के लिए आर्कपी कार्य नीचे है। फीचर कक्षाएं अनुमानित हैं (ब्रिटिश नेशनल ग्रिड)। क्या एक अतिरिक्त कदम है जो मुझे एक मानचित्र डोकुम से दूर अजगर में कोणों की गणना करने के लिए लेना होगा
एंडी

जवाबों:


13

अपेक्षाकृत सरल वर्कफ़्लो है। यह उन संभावित समस्याओं को खत्म करता है जो दो सुविधाओं को एक से अधिक बिंदुओं में काट सकती हैं। इसके लिए स्क्रिप्टिंग की आवश्यकता नहीं है (लेकिन आसानी से इसे स्क्रिप्ट में बदल दिया जा सकता है)। यह मुख्य रूप से आर्कगिस मेनू से किया जा सकता है।

विचार चौराहे के बिंदुओं की एक परत का दोहन करने के लिए है, प्रत्येक अलग-अलग जोड़े को पॉलीसिनेज़ के लिए एक बिंदु। आपको इन चौराहों बिंदुओं पर प्रत्येक इंटरसेक्टिंग पॉलीलाइन का एक छोटा सा टुकड़ा प्राप्त करने की आवश्यकता है । इन टुकड़ों के झुकावों का उपयोग उनके प्रतिच्छेदन कोणों की गणना करने के लिए करें।

यहाँ कदम हैं:

  1. सुनिश्चित करें कि प्रत्येक पॉलीलाइन विशेषताओं में इसकी विशेषता तालिका के भीतर एक विशिष्ट पहचानकर्ता है। इसका उपयोग बाद में पॉलीनेस की कुछ ज्यामितीय विशेषताओं को प्रतिच्छेदन बिंदु तालिका में शामिल करने के लिए किया जाएगा।

  2. जियोप्रोसेसिंग | इंट्रैक्ट अंक प्राप्त करता है (यह सुनिश्चित करें कि आप आउटपुट के लिए अंक चाहते हैं )।

  3. जियोप्रोसेसिंग | बफर आपको एक छोटी राशि द्वारा अंक बफर करने देता है। इसे वास्तव में छोटा करें ताकि एक बफर के भीतर प्रत्येक पंक्ति का हिस्सा झुकता न हो।

  4. जियोप्रोसेसिंग | क्लिप (दो बार लागू) मूल पॉलीलाइन परतों को सिर्फ बफ़र्स तक सीमित करता है। क्योंकि यह अपने आउटपुट के लिए नए डेटासेट का उत्पादन करता है, बाद के संचालन मूल डेटा (जो कि एक अच्छी बात है) को संशोधित नहीं करेगा।

    आकृति

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

  5. प्रत्येक क्लिप्ड परतों में चार नए फ़ील्ड बनाने के लिए AddField टूल का उपयोग करें : [X0], [Y0], [X1] और [Y1]। वे बिंदु निर्देशांक धारण करेंगे, इसलिए उन्हें युगल बनाएं और उन्हें बहुत अधिक सटीकता दें।

  6. ज्यामिति की गणना करें (प्रत्येक नए फ़ील्ड हेडर पर राइट-क्लिक करके आमंत्रित किया गया) आपको x- और y- प्रत्येक क्लिप किए गए पॉलीलाइन के प्रारंभ और अंत बिंदुओं के निर्देशांक की गणना करने में सक्षम बनाता है: इन्हें [X0], [Y0], [X1] में डालें। , और [Y1], क्रमशः। यह प्रत्येक क्लिप्ड परत के लिए किया जाता है, इसलिए 8 गणनाओं की आवश्यकता होती है।

  7. चौराहे बिंदु परत में एक नया [कोण] क्षेत्र बनाने के लिए AddField टूल का उपयोग करें ।

  8. सामान्य ऑब्जेक्ट आइडेंटिफ़ायर के आधार पर चौराहे के पॉइंट टेबल पर क्लैप्ड टेबल से जुड़ें । (परत नाम पर राइट-क्लिक करके और "जॉइन और रिलेट्स" का चयन करके जॉइन किया जाता है।

    इस बिंदु पर प्रतिच्छेदन तालिका में 9 नए क्षेत्र हैं: दो का नाम [X0], आदि है, और एक का नाम [कोण] है। अन्य नाम [X0], [Y0], [X1] और [Y1] फ़ील्ड जो सम्मिलित तालिकाओं में से एक से संबंधित हैं। आइए इनको कॉल करें (कहें) "X0a", "Y0a", "X1a", और "Y1a"।

  9. चौराहे की तालिका में कोण की गणना करने के लिए फ़ील्ड कैलकुलेटर का उपयोग करें। यहाँ गणना के लिए एक पायथन कोड ब्लॉक है:

    dx = !x1!-!x0!
    dy = !y1!-!y0!
    dxa = !x1a!-!x0a!
    dya = !y1a!-!y0a!
    r = math.sqrt(math.pow(dx,2) + math.pow(dy,2))
    ra = math.sqrt(math.pow(dxa,2) + math.pow(dya,2))
    c = math.asin(abs((dx*dya - dy*dxa))/(r*ra)) / math.pi * 180

    क्षेत्र गणना की अभिव्यक्ति, निश्चित रूप से, केवल है

    c

इस कोड ब्लॉक की लंबाई के बावजूद, गणित सरल है: (डीएक्स, डाई) पहली पॉलीलाइन के लिए एक दिशा वेक्टर है और (डीएक्सए, डीएए) दूसरे के लिए एक दिशा वेक्टर है। उनकी लंबाई, आर और आरए (पायथागॉरियन प्रमेय के माध्यम से गणना की जाती है), उन्हें यूनिट वैक्टर को सामान्य करने के लिए उपयोग किया जाता है। (वहाँ शून्य लंबाई के साथ कोई समस्या नहीं होनी चाहिए, क्योंकि क्लिपिंग को सकारात्मक लंबाई की सुविधाओं का उत्पादन करना चाहिए।) उनके वेज उत्पाद का आकार dx dya - dydxa (r और ra द्वारा विभाजन के बाद) कोण की साइन है। (सामान्य आंतरिक उत्पाद के बजाय कील उत्पाद का उपयोग करना लगभग शून्य कोण के लिए बेहतर संख्यात्मक परिशुद्धता प्रदान करना चाहिए।) अंत में, कोण रेडियन से डिग्री में परिवर्तित हो जाता है। परिणाम 0 और 90 के बीच रहेगा। त्रिकोणमिति के परिहार पर ध्यान दें, जब तक कि अंत नहीं हो जाता: यह दृष्टिकोण विश्वसनीय और आसानी से गणना किए गए परिणामों का उत्पादन करता है।

कुछ बिंदु चौराहे की परत में कई बार दिखाई दे सकते हैं। यदि हां, तो उन्हें उनसे जुड़े कई कोण मिलेंगे।

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


1
यह काम कर सकता है, लेकिन आप कोडब्लॉक में फ़ील्ड नामों का संदर्भ नहीं दे सकते हैं, इसलिए आपको किसी फ़ंक्शन में कोड को लपेटना होगा और फ़ील्ड नामों का उपयोग तर्क के रूप में करना होगा।
म्वेक्सेल

@ एमवी उस अवलोकन के लिए धन्यवाद। अजगर की जगह वीबीएस का भी इस्तेमाल किया जा सकता है - वीबीएस कोड ब्लॉक में फील्ड नामों को पार्स करेगा
whuber

1
यह वास्तव में एक समारोह आवरण का उपयोग करते समय एक आकर्षण की तरह काम करता था। मैंने पाया कि आर्कगिस 10 में और जब पायथन का उपयोग कर रहे हैं, तो आपको चर को उर्फ ​​करने की आवश्यकता नहीं है, आप फ़ील्ड संदर्भ में शामिल तालिका नाम को पसंद कर सकते हैं, जैसे !table1.x0!
मुवेक्सेल

6

मेरा मानना ​​है कि आपको अजगर की स्क्रिप्ट बनाने की आवश्यकता है।

आप इसे जियोप्रोसेसिंग टूल और आर्कपी का उपयोग करके कर सकते हैं।

यहाँ मुख्य उपकरण और विचार हैं जो आपके लिए उपयोगी हो सकते हैं:

  1. उपकरण का उपयोग कर - अपने दो पॉलीलाइन के मेक चौराहे featureclasses (POINT_FC आपको इसके परिणामस्वरूप सुविधाओं बात की जरूरत है) (उन्हें PLINE_FC1, PLINE_FC2 फोन की सुविधा देता है) इंटरसेक्ट । आपके पास बिंदु POINT_FC में PLINE_FC1, PLINE_FC2 से ID होंगे।
  2. बिंदु पर उपकरण स्प्लिट लाइन का उपयोग करके POINT_FC द्वारा भाजित PLINE_FC1। परिणाम से आप पॉलीइन्स को अलग कर देंगे - इसका मुख्य लाभ यह है कि आप इस तरह की लाइन के पहले / आखिरी शीर्ष को ले सकते हैं, इसकी तुलना अगले / पिछले वर्टेक्स (समन्वय अंतर) से कर सकते हैं और कोण की गणना कर सकते हैं। तो, आपके पास अंतर रेखा के बिंदु में आपकी रेखा का कोण होगा। यहां एक समस्या है - आपको आउटपुट कैसे लिखा जाता है, इसका एहसास करने के लिए आपको इस टूल को कई बार मैन्युअल रूप से चलाना होगा। मेरा मतलब है कि अगर यह पॉलीलाइन लेता है, तो इसे विभाजित करें, आउटपुट के लिए दो परिणाम पॉलीलाइन लिखें और फिर अगली पॉलीलाइन पर जाएं और दोहराएं। या यह हिस्सा हो सकता है (बंटवारे का परिणाम) अलग-अलग मेमोरी फ़ीचर वर्गों को लिखा जाता है, फिर आउटपुट में जोड़ा जाता है। यह मुख्य समस्या है - यह महसूस करने के लिए कि आउटपुट को विभाजित करने के बाद प्रत्येक पॉलीलाइन के केवल पहले भाग को फ़िल्टर करने में सक्षम होने के लिए कैसे लिखा जाता है। एक अन्य संभावित समाधान है लूप थ्रोट के साथ सभी परिणामित पॉलीइलीन के साथSearchCursor और केवल पहले सामना करना पड़ा (स्रोत पॉलीनेन्स PLINE_FC1 की आईडी द्वारा)।
  3. कोण प्राप्त करने के लिए आपको चापलूसी का उपयोग करके परिणाम पॉलीलाइन की वर्टिकल तक पहुंचना होगा । अंक (POINT_FC) के लिए परिणामी कोण लिखें।
  4. PLINE_FC2 के लिए 2-3 चरण दोहराएं।
  5. स्थान एट्रिब्यूट विशेषताएँ (POINT_FC में) और परिणाम प्राप्त करें।

हो सकता है कि चरण 2 को कोड करना भी बहुत मुश्किल होगा (कुछ उपकरणों के लिए ArcInfo लाइसेंस की आवश्यकता होती है)। फिर आप हर पॉलीलाइन के वर्टिकल का विश्लेषण करने की कोशिश कर सकते हैं (उन्हें चौराहे के बाद आईडी द्वारा समूहित कर सकते हैं)।

यहाँ यह करने का तरीका है:

  1. पहले चौराहे बिंदु POINT_FC को लें। इसके निर्देशांक प्राप्त करें ( point_x, point_y)
  2. इसकी आईडी द्वारा PLINE_FC1 से संबंधित स्रोत पॉलीलाइन लें।
  3. पहले ( और vert0_x, vert0_y) और दूसरे ( vert1_x, vert1_y) को लें।
  4. पहले शीर्ष के लिए इस शीर्ष और चौराहे बिंदु के बीच की रेखा की स्पर्शरेखा की गणना करें: tan0 = (point_y - vert0_y) / (point_x - vert0_x)
  5. दूसरे शीर्ष के लिए एक ही चीज़ की गणना करें: tan1 = (vert1_y - point_y) / (vert1_x - point_x)
  6. यदि tan1के बराबर है tan2, तो आपको अपनी रेखा के दो कोने मिलेंगे, जिनके बीच में चौराहा बिंदु है और आप इस रेखा से चौराहे के कोण की गणना कर सकते हैं। अन्यथा आपको वर्धमान की दूसरी जोड़ी (दूसरी, तीसरी) और इसी तरह आगे बढ़ना होगा।
  7. प्रत्येक चौराहे बिंदु के लिए चरण 1-6 दोहराएं।
  8. दूसरे पॉलीलाइन फीचरक्लास PLINE_FC2 के लिए चरण 1-7 दोहराएं।
  9. PLINE_FC1 और PLINE_FC2 से कोण एट्रिब्यूट विशेषताएँ और परिणाम प्राप्त करें।

1

हाल ही में मैं इसे अपने दम पर करने की कोशिश कर रहा था।

मेरा क्लू फ़ीचर लाइनों के चौराहों के साथ-साथ चौराहों से एक-मीटर की दूरी पर स्थित बिंदुओं के चारों ओर गोलाकार बिंदुओं पर आधारित है। आउटपुट पॉलीलाइन फीचर क्लास है जिसमें चौराहों और कोणों पर कोणों की संख्या के गुण हैं।

ध्यान दें कि चौराहों को खोजने के लिए लाइनों को योजनाबद्ध किया जाना चाहिए और स्थानिक संदर्भ को सही लाइन लंबाई प्रदर्शन (मेरा WGS_1984_Web_Mercator_Auxiliary_Sphere) के साथ सेट किया जाना है।

ArcMap कंसोल में चल रहा है लेकिन आसानी से टूलबॉक्स में स्क्रिप्ट में बदल सकता है। यह स्क्रिप्ट टीओसी में केवल लाइन लेयर का उपयोग करती है, इससे अधिक कुछ नहीं।

import arcpy
import time

mxd = arcpy.mapping.MapDocument("CURRENT")
df = mxd.activeDataFrame


line = ' * YOUR POLYLINE FEATURE LAYER * ' # paste the name of line layer here    

def crossing_cors(line_layer):
    mxd = arcpy.mapping.MapDocument("CURRENT")
    df = mxd.activeDataFrame
    arcpy.env.overwriteOutput = True
    sr = arcpy.Describe(line_layer).spatialReference

    dict_cors = {}
    dang_list = []

    with arcpy.da.UpdateCursor(line_layer, ['SHAPE@', 'OID@']) as uc:
        for row in uc:
            if row[0] is None:
                uc.deleteRow()

    with arcpy.da.UpdateCursor(line_layer, 'SHAPE@', spatial_reference = sr) as uc:
        for row in uc:
            line = row[0].getPart(0)
            for cor in line:
                coord = (cor.X, cor.Y)
                try:
                    dict_cors[coord] += 1
                except:
                    dict_cors[coord] = 1
    cors_only = [f for f in dict_cors if dict_cors[f]!=1]
    cors_layer = arcpy.CreateFeatureclass_management('in_memory', 'cross_pnt', "POINT", spatial_reference = sr)
    arcpy.AddField_management(cors_layer[0], 'ANGLE_NUM', 'LONG')
    with arcpy.da.InsertCursor(cors_layer[0], ['SHAPE@', 'ANGLE_NUM']) as ic:
        for x in cors_only:
            pnt_geom = arcpy.PointGeometry(arcpy.Point(x[0], x[1]), sr)
            ic.insertRow([pnt_geom, dict_cors[x]])
    return cors_layer

def one_meter_dist(line_layer):
    mxd = arcpy.mapping.MapDocument("CURRENT")
    df = mxd.activeDataFrame
    arcpy.env.overwriteOutput = True
    sr = arcpy.Describe(line_layer).spatialReference

    dict_cors = {}
    dang_list = []
    cors_list = []
    with arcpy.da.UpdateCursor(line_layer, 'SHAPE@', spatial_reference = sr) as uc:
        for row in uc:
            line = row[0]
            length_line = line.length 
            if length_line > 2.0:
                pnt1 = line.positionAlongLine(1.0)
                pnt2 = line.positionAlongLine(length_line - 1.0)
                cors_list.append(pnt1)
                cors_list.append(pnt2)
            else:
                pnt = line.positionAlongLine(0.5, True)
    cors_layer = arcpy.CreateFeatureclass_management('in_memory', 'cross_one_meter', "POINT", spatial_reference = sr)
    ic = arcpy.da.InsertCursor(cors_layer[0], 'SHAPE@')
    for x in cors_list:
        ic.insertRow([x])
    return cors_layer

def circles(pnts):

    import math
    mxd = arcpy.mapping.MapDocument("CURRENT")
    df = mxd.activeDataFrame
    arcpy.env.overwriteOutput = True
    sr = df.spatialReference

    circle_layer = arcpy.CreateFeatureclass_management('in_memory', 'circles', "POINT", spatial_reference = sr)


    ic = arcpy.da.InsertCursor(circle_layer[0], 'SHAPE@')
    with arcpy.da.SearchCursor(pnts, 'SHAPE@', spatial_reference = sr) as sc:
        for row in sc:
            fp = row[0].centroid
            list_circle =[]
            for i in xrange(0,36):
                an = math.radians(i * 10)
                np_x = fp.X + (1* math.sin(an))
                np_y = fp.Y + (1* math.cos(an))
                pnt_new = arcpy.PointGeometry(arcpy.Point(np_x,np_y), sr)

                ic.insertRow([pnt_new])
    del ic 
    return circle_layer

def angles(centers, pnts, rnd):
    mxd = arcpy.mapping.MapDocument("CURRENT")
    df = mxd.activeDataFrame
    sr = df.spatialReference

    line_lyr = arcpy.CreateFeatureclass_management('in_memory', 'line_angles', "POLYLINE", spatial_reference = sr)
    arcpy.AddField_management(line_lyr[0], 'ANGLE', "DOUBLE")
    arcpy.AddField_management(line_lyr[0], 'ANGLE_COUNT', "LONG")

    ic = arcpy.da.InsertCursor(line_lyr[0], ['SHAPE@', 'ANGLE', 'ANGLE_COUNT'])

    arcpy.AddField_management(pnts, 'ID_CENT', "LONG")
    arcpy.AddField_management(pnts, 'CENT_X', "DOUBLE")
    arcpy.AddField_management(pnts, 'CENT_Y', "DOUBLE")
    arcpy.Near_analysis(pnts, centers,'',"LOCATION") 

    with arcpy.da.UpdateCursor(line, ['SHAPE@', 'OID@']) as uc:
        for row in uc:
            if row[0] is None:
                uc.deleteRow()

    with arcpy.da.UpdateCursor(pnts, [u'ID_CENT', u'CENT_X', u'CENT_Y', u'NEAR_FID', u'NEAR_DIST', u'NEAR_X', u'NEAR_Y'], spatial_reference = sr) as uc:
        for row in uc:
            row[0] = row[3]
            row[1] = row[5]
            row[2] = row[6]
            uc.updateRow(row)
            if row[4] > 1.1:
                uc.deleteRow()


    arcpy.Near_analysis(pnts, rnd,'',"LOCATION")     

    list_id_cent = []
    with arcpy.da.UpdateCursor(pnts, [u'ID_CENT', u'CENT_X', u'CENT_Y', u'NEAR_FID', u'NEAR_DIST', u'NEAR_X', u'NEAR_Y', 'SHAPE@'], spatial_reference = sr) as uc:
        for row in uc:
            pnt_init = (row[-1].centroid.X, row[-1].centroid.Y)
            list_id_cent.append([(row[1], row[2]), row[3], pnt_init])

    list_id_cent.sort()
    values = set(map(lambda x:x[0], list_id_cent))
    newlist = [[y for y in list_id_cent if y[0]==x] for x in values]

    dict_cent_angle = {}

    for comp in newlist:
        dict_ang = {}
        for i, val in enumerate(comp):

            curr_pnt = comp[i][2]
            prev_p = comp[i-1][2]
            init_p = comp[i][0]


            angle_prev = math.degrees(math.atan2(prev_p[1]-init_p[1], prev_p[0]-init_p[0]))
            angle_next = math.degrees(math.atan2(curr_pnt[1]-init_p[1], curr_pnt[0]-init_p[0]))

            diff = abs(angle_next-angle_prev)%180


            vec1 = [(curr_pnt[0] - init_p[0]), (curr_pnt[1] - init_p[1])]
            vec2 = [(prev_p[0] - init_p[0]), (prev_p[1] - init_p[1])]

            ab = (vec1[0] * vec2[0]) + (vec1[1] * vec2[1]) 
            mod_ab = math.sqrt(math.pow(vec1[0], 2) + math.pow(vec1[1], 2)) * math.sqrt(math.pow(vec2[0], 2) + math.pow(vec2[1], 2))
            cos_a = round(ab/mod_ab, 2)

            diff = math.degrees(math.acos(cos_a))

            pnt1 = arcpy.Point(prev_p[0], prev_p[1])
            pnt2 = arcpy.Point(init_p[0], init_p[1])
            pnt3 = arcpy.Point(curr_pnt[0], curr_pnt[1])


            line_ar = arcpy.Array([pnt1, pnt2, pnt3])
            line_geom = arcpy.Polyline(line_ar, sr)

            ic.insertRow([line_geom , diff, len(comp)])
    del ic

    lyr_lst = [f.name for f in arcpy.mapping.ListLayers(mxd)]
    if 'line_angles' not in lyr_lst:
        arcpy.mapping.AddLayer(df, arcpy.mapping.Layer(line_lyr[0]))


centers = crossing_cors(line)

pnts = one_meter_dist(line)

rnd = circles(centers)

angle_dict = angles(centers, pnts, rnd)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.