شاید برای شما هم پیش آمده باشید که یک لایه خطی- مثلا شبکه معابر، راه ها، رودخانه ها و…- داشته و بخواهید بدانید هر کدام از خطوط این لایه با چه خطوطی ارتباط دارد و به چه خطوطی وصل است. اما لایه خطی به خودی خود هیچ اطلاعی در این زمینه در اختیار شما قرار نمی دهد.
البته در بسیاری از موارد که به چنین اطلاعی نیاز هست معمولا پای یک آنالیز شبکه در میان است و چون آنالیزهای شبکه را می توان با ساخت یک شبکه هندسی (Geometric Network) از روی لایه خطی مورد نظر در ArcCatalog یا ArcMap و سپس استفاده از این شبکه هندسی در آنالیز به انجام رساند طبیعتا نیاز شما به دانستن ارتباطات بین خطوط مرتفع می شود؛ چرا که شبکه هندسی همه این ارتباطات را درون خود دارد.
اما شبکه هندسی این ارتباطات را در اختیار شما قرار نمی دهد بلکه به طور ضمنی درون خود ذخیره می کند. شما از شبکه هندسی تنها یک لایه خطی و یک لایه نقطه ای مربوط به گره ها را خواهید دید. (گره محل تقاطع خطوط است که می تواند نمایانگر چهارراه، میدان، …. باشد). کاری که اینجا برای حل مشکل در پی انجام آن هستیم افزودن دو فیلد به لایه خطی است که گره ابتدایی و گره انتهایی هر خط را مشخص می کنند. با وجود این دو فیلد- ولو که لایه گره ها را نداشته باشید- باز می توانید ارتباطات بین خطوط را تعیین کنید. کافی است در جدول مقدار گره ابتدایی و انتهایی خط مورد نظر را خوانده و سپس با انجام یک تحلیل Select By Attribute ببینید چه عوارضی در فیلد گره ابتدایی و انتهایی مقدار این دو گره وجود دارد. این عوارض همان خطوطی هستند که به خط موردنظر ما متصل هستند.
اما فیلد گره ابتدایی (From_Node) و گره انتهایی (To_Node) را چگونه باید ساخت؟ اینجاست که کد زیر که در ArcObjects 10 نوشته شده است به کمک شما می آید. اما قبل از پرداختن به کد:
1- از دستور Planarize Lines در نوارابزار Toplogy برای شکستن خطوط در جایی که اتصال وجود دارد استفاده کنید. این دستور باعث می شود که خطوطی که از روی همدیگر عبور کرده اند در محل تقاطع به خطوط کوچکتری شکسته شوند. (برای استفاده از این گزینه باید Start Editing از تولبار Editing را فعال کرده و سپس تمام عوارض درون لایه را انتخاب کنید تا دکمه Planarize فعال شود.)
2- یک Network Dataset از روی لایه خطی بسازید. با این عمل شما یک لایه نقطه ای به نام Junctions دارید که محل تقاطع ها را به شما نشان می دهید. از این لایه نقطه ای یک خروجی Shapefile بگیرید. در ادامه از این لایه استفاده خواهیم کرد.
اصل برنامه که در محیط VB.NET و ArcGIS 10 نوشته شده به شکل زیر است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
Dim pMxDoc As ESRI.ArcGIS.ArcMapUI.IMxDocument = My.ArcMap.Application.Document Dim pMap As IMap = pMxDoc.FocusMap Dim pointFtrLyr As IFeatureLayer pointFtrLyr = pMap.Layer(0) Dim lineFtrLyr As IFeatureLayer lineFtrLyr = pMap.Layer(1) Dim lineFC As IFeatureClass lineFC = lineFtrLyr.FeatureClass Dim fromNodeIndex As Integer fromNodeIndex = lineFC.FindField("FROM_NODE") Dim toNodeIndex As Integer toNodeIndex = lineFC.FindField("TO_NODE") Dim pFI2 As IFeatureIndex2 pFI2 = New FeatureIndex pFI2.FeatureClass = pointFtrLyr.FeatureClass pFI2.OutputSpatialReference("Shape") = pMxDoc.FocusMap.SpatialReference pFI2.Index(Nothing, pointFtrLyr.AreaOfInterest) Dim m_IQ2 As IIndexQuery2 m_IQ2 = pFI2 Dim pLineCursor As IFeatureCursor pLineCursor = lineFtrLyr.Search(Nothing, False) Dim pLineFeature As IFeature pLineFeature = pLineCursor.NextFeature Dim foid As Long Dim toid As Long Dim fdist As Double Dim tdist As Double While Not pLineFeature Is Nothing Dim pLine As IPolyline pLine = pLineFeature.Shape m_IQ2.NearestFeature(pLine.FromPoint, foid, fdist) If Math.Round(fdist, 0) = 0 Then pLineFeature.Value(pLineFeature.Fields.FindField("FROM_NODE")) = foid pLineFeature.Store() End If m_IQ2.NearestFeature(pLine.ToPoint, toid, tdist) If Math.Round(tdist, 0) = 0 Then pLineFeature.Value(pLineFeature.Fields.FindField("TO_NODE")) = toid pLineFeature.Store() End If pLineFeature = pLineCursor.NextFeature Loop MsgBox("Features updated!!") |
در این کد فرض شده که در محیط ArcGIS، لایه گره ها (Nodes.shp) لایه اول و لایه خطی شما لایه دوم از فهرست لایه هاست. این کد برای قالب AddIn و در Visual Studio 2008 نوشته شده است و در محیط ArcObjects قابل استفاده است. برای محیط ArcEngine کد فوق نیاز به تغییراتی جزئی در بخش معرفی نقشه و لایه ها در ابتدای برنامه خواهد داشت.
همچنین برای اجرای کد فوق نیاز دارید تا ارجاعاتی (Reerences) را به کتابخانه های Carto ، Geodatabase و Geometry به پروژه خود در Visual Studio اضافه کرده و این کتابخانه در بالای کلاس خود تعریف کنید. تعریف این کلاس ها در VB.NET با دستورات زیر انجام می شود که قبل از اولین خط تعریف کلاس قرار می گیرند:
1 2 3 4 5 |
Imports ESRI.ArcGIS.Carto Imports ESRI.ArcGIS.Geodatabase Imports ESRI.ArcGIS.Geometry |
کد فوق دو فیلد From_Node و To_Node به لایه خطی شما اضافه می کند که حاوی FID گره ابتدایی و انتهایی هر خط هستند. حال می توانید لایه گره ها را حذف کرده و از لایه خطی خود برای انجام آنالیزهایی که نیاز دارید استفاده کنید.
سلام و خدا قوت
از اینکه این همه مطالب علمی و کاربردی را در خدمت دیگران قرار می دهید بسیار سپاسگزارم. ان شاالله خداوند به شما عزیزان توفیق بیشتر بدهد. باز از سایت خوب و آموزنده شما کمال تشکر را دارم.
سلام بر حضرات محترم . بابت مطالب دوستان تشکر می کنم بنده در زمینه نرم افزار ARC GIS و علم GIS چندین سال است که فعالیت می کنم و پروژه های مختلفی را انجام داده ام از جمله دز زمینه شبکه گاز ، GIS Ready شهرداری، طرح های هادی بنیاد مسکن ، عضو انجمن های و گروه های GIS شرکت ESRI هستم و … اما غرض از گفتن این مطالب اینه که بابت gis به لطف خدا یه چیزایی بلد هستم ولی می خواستم در زمینه برنامه نویسی GIS اطلاع کسب کنم من آشنایی نسبی با VB6 و VB.NET و همچنین کتاب ترجمه آقای مهتدس هاشمی که در زمینه برنامه نویسی با ARC Object است را هم دارم ولی اگر کسی از دوستان تا حالا برای arcgis برنامه نویسی کرده در این رابطه اگر امکانش باشه کمکم کنه ممنون میشم.
میتونید با ایمیل info@GISTech.ir تماس بگیرید
موفق باشید.
با سلام و عرض خسته نباشید
من با اینکه خودم دانشجوی GIS هستم و برای پیشبرد موضوع تز دقیقاً همین کدها رو لازم داشتم واقعاً سوادشو نداشتم و اگرم میخواستم خودم شروع کنم به یادگیری زمان رو از دست می دادم بنابراین تشکر دارم از مدیر سایت و کسی که کدها رو گذاشته. انشاءا… به هر هدف خیری که دارید برسید و اگه تونستم جبران میکنم.