Can I use a local GML to load to the map as a new layer?

6684
11
08-07-2012 04:51 AM
Labels (1)
MarkSantos
New Contributor
I have a GML file and I would like to load it to my map. I am using ArcGIS Runtime SDK for WPF in C#. Which layer can I use to do this? Will it give me the same functionality as to what I can do with GML files in ArcGIS Desktop?

Thanks!
0 Kudos
11 Replies
MichaelBranscomb
Esri Frequent Contributor
Hi,

There is no direct support for GML in the ArcGIS Runtime SDK for WPF. However, if this is a key requirement for you, you could consider writing a custom layer. An example of this (the KML layer implementation) can be found in the ESRI.ArcGIS.Client.Toolkit.Datasources source code available on codeplex: http://esrisilverlight.codeplex.com/releases/view/80697. Download the source code then look in "ESRIToolkitSource_v2.4.zip\WPF\ESRI.ArcGIS.Client.Toolkit.DataSources\Kml".

Cheers

Mike
0 Kudos
MarkSantos
New Contributor
Hi,

There is no direct support for GML in the ArcGIS Runtime SDK for WPF. However, if this is a key requirement for you, you could consider writing a custom layer. An example of this (the KML layer implementation) can be found in the ESRI.ArcGIS.Client.Toolkit.Datasources source code available on codeplex: http://esrisilverlight.codeplex.com/releases/view/80697. Download the source code then look in "ESRIToolkitSource_v2.4.zip\WPF\ESRI.ArcGIS.Client.Toolkit.DataSources\Kml".

Cheers

Mike


Oh. Alright. I guess that's the only solution for now. I hope you'll support GML soon.

Thank you very much.
0 Kudos
MichaelBranscomb
Esri Frequent Contributor
Hi,

If you'd like to see GML supported as a standard feature please submit the idea over on the ArcGIS Ideas site (http://ideas.arcgis.com/ideaList?category=ArcGIS+Runtime) - we regularly review the ideas posted here and based on demand/feedback will consider them for inclusion in the product in a future release. No one has yet posted GML as a request as far as I'm aware.

Cheers

Mike
0 Kudos
AnkitaBhatia
New Contributor III
Hi!
Is GML supported in ArcGIS runtime SDK for wpf 10.1.1?
I am very new to this and would like to confirm if there are any risks involved in writing a custom layer as mentioned above!

Also, the data I need to access comes from am excel and I have to thus draw everything on a graphic layer. I feel this would be a performance overhead. Am I right in thinking so?
Is there an alternative way (may be some format that I can convert my excel data into, to render on map) to use all the tools provided by ESRI, like they work with feature layer.
0 Kudos
BrianLocke
Occasional Contributor II
I was able to pass sentences back and forth to SQL Server 2008 R2 using GML.
GML is just XML, so you may use xmlwriter  and many other classes to retreive the data from attributes and elements(GML,KML all xml!)
you could even do this with GeoRSS I suppose. 


Example for creating GML for Point Information going into SQL Server c#

  public static string latLongToXML (decimal lat, decimal Long)        
        {

            StringBuilder GeoXMLStr = new StringBuilder();
            XmlWriterSettings xWSettings = new XmlWriterSettings();
            xWSettings.OmitXmlDeclaration = true;

            XmlWriter xW = XmlWriter.Create(GeoXMLStr, xWSettings);
            using (xW)
            {
                xW.WriteStartElement("Point", "http://www.opengis.net/gml");
                xW.WriteStartElement("pos");
                xW.WriteRaw(lat.ToString() + " " + Long.ToString());
                xW.WriteEndElement();
                xW.WriteEndElement();
                xW.Flush();
                xW.Close();
            }
            return GeoXMLStr.ToString();
0 Kudos
BrianLocke
Occasional Contributor II
Can Even do the same for coming out and in for Polygons as well here is my VB class
Imports System
Imports System.Data
Imports System.Xml
Imports System.Text
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.IO


Imports ESRI.ArcGISExplorer
Imports ESRI.ArcGISExplorer.Application
Imports ESRI.ArcGISExplorer.Geometry
Imports ESRI.ArcGISExplorer.Mapping
Imports ESRI.ArcGISExplorer.Data
Imports ESRI.ArcGISExplorer.Threading
Imports Microsoft.VisualBasic

Public Class GML
    Public Type As String = Nothing

    Friend WithEvents InciTableAdapter As New Inci.WRMSDataSetTableAdapters.InciTableAdapter
    Friend WithEvents WRMSDataSet As New Inci.WRMSDataSet
    Friend WithEvents GMLRtrnDataTable As New DataTable
    Private disp As MapDisplay = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay

    Public Sub PerimGet(ByVal InciName As String)
        Me.InciTableAdapter.FillByInciNumber(WRMSDataSet.Inci, InciName)
        For Each InfoRow In Me.WRMSDataSet.Inci
            InfoRow("GML").ToString()
        Next InfoRow
    End Sub

    Public Function XMLToGeom(ByVal XMLGeo As String)
        Dim Perim As Polygon = New Polygon()
        Using XMLRead As XmlReader = XmlReader.Create(New StringReader(XMLGeo))
            XMLRead.ReadToFollowing("posList")

            Dim LatLongStrArr() As String = (XMLRead.ReadElementContentAsString()).Split(" ")
            For I = LatLongStrArr.Length - 1 To 0 Step -2
                Perim.AddPoint(ESRI.ArcGISExplorer.Geometry.Point.CreateFromLatitudeLongitude(CDbl(LatLongStrArr(I - 1).ToString), CDbl(LatLongStrArr(I).ToString)))
            Next I
            Perim.Close()
            Return Perim
            End
            Using resource As New Object

            End Using


    End Function

    Public Sub CreateNwInci(ByVal InciName As String, ByVal InciNumber As String, ByVal InciType As String, ByVal GeomAsXML As String)
        'Inserts Incident data into the WRMS Datatables

        Try
            Me.InciTableAdapter.USP_CrtNwInci(InciName, InciNumber, InciType, GeomAsXML, Now)
            GetInci(InciNumber)
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try
    End Sub

    Public Function GeomToXML(ByVal GObj As Geometry)
        Dim GeoPoly As Polygon = GObj
        Dim GeoXMLStr As New StringBuilder

        Dim XwSettings As XmlWriterSettings = New XmlWriterSettings()
        XwSettings.OmitXmlDeclaration = True

        Using Xw As XmlWriter = XmlWriter.Create(GeoXMLStr, XwSettings)

            Xw.WriteStartElement("Polygon", "http://www.opengis.net/gml")
            Xw.WriteStartElement("exterior")
            Xw.WriteStartElement("LinearRing")
            Xw.WriteStartElement("posList")
            For Pt = GeoPoly.PointCount - 1 To 0 Step -1
                Xw.WriteRaw(GeoPoly.GetPoint(Pt).GetLatitude.ToString("####.000000") + " " + GeoPoly.GetPoint(Pt).GetLongitude.ToString("####.000000") + " ")
            Next Pt
            Xw.WriteEndElement()
            Xw.WriteEndElement()
            Xw.WriteEndElement()
            Xw.WriteEndElement()
            Xw.Flush()
            Xw.Close()
        End Using

        Return GeoXMLStr.ToString

    End Function

    Public Sub GetInci(ByVal InciNumber As String)
        GMLRtrnDataTable = Me.InciTableAdapter.GetDataByInciNumber(InciNumber)

        For Each Row As DataRow In GMLRtrnDataTable.Rows
            Dim PerimNt As New Note(Row("Inci_Name").ToString(), _
                                     XMLToGeom(Row("GML").ToString()), _
                                     Symbol.Fill.Solid.Red)
            PerimNt.Popup.Content = "Acres: " + Row("Inci_Acreage").ToString()


            disp.Map.ChildItems.Add(PerimNt)
        Next Row
    End Sub


End Class
0 Kudos
BrianLocke
Occasional Contributor II


and class for reading Automated Flight Following KML in Runtime c#
using WRMS.Framework.Utilities;
using System.ComponentModel;
using System.Windows.Input;
using WRMS.Framework.Commands;
using Microsoft.Win32;
using System.IO;
using System.Xml;
using System.Net;
using Ionic.Zip;
using System;
using System.Windows.Documents;
using System.Collections.Generic;
using System.Xml.Linq;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using System.Text.RegularExpressions;
using AffCore;

namespace WRMS.Framework.ViewModels
{
    class AffVM : MapHelper, INotifyPropertyChanged
    {
        GraphicsLayer graphicsLayer = _map.Layers["affResourcesGraphicsLayer"] as GraphicsLayer;

        OpenFileDialog ofd;

        XmlDocument affFileObj = new XmlDocument();
        

        string resourceUrl;

        private string _path;
        public string path
        {
            get { return _path; }
            set
            {
                if (_path != value)
                {
                    _path = value;
                    onPropertyChanged("url");
                }
            }
        }

        private string _bytesReceivedDisp;
        public string bytesReceivedDisp
        {
            get { return _bytesReceivedDisp; }
            set
            {
                if (_bytesReceivedDisp!=value)
                {
                    _bytesReceivedDisp = value;
                    onPropertyChanged("bytesReceivedDisp");
                    
                }
            }
        }

        private string _totalBytesDisp;
        public string totalBytesDisp
        {
            get { return _totalBytesDisp; }
            set
            {
                if (_totalBytesDisp!=value)
                {       
                    _totalBytesDisp = value;
                    onPropertyChanged("totalBytesDisp");
                }
            }
        }

        private double _bytesReceived;
        public double bytesReceived
        {
            get { return _bytesReceived; }
            set
            {
                if (_bytesReceived != value)
                {
                    _bytesReceived = value;
                    onPropertyChanged("bytesReceived");
                }
            }
        }

        private double _totalBytes = 100;
        public double totalBytes
        {
            get { return _totalBytes; }
            set
            {
                if (_totalBytes != value)
                {
                    _totalBytes = value;
                    onPropertyChanged("totalBytes");
                }
            }
        }

        private string _status;
        public string status
        {
            get { return _status; }
            set
            {
                if (_status != value)
                {
                    _status = value;
                    onPropertyChanged("status");
                }
            }
        }

        private bool _isDisplayed;
        public bool isDisplayed
        {
            get { return _isDisplayed; }
            set
            {
                if (_isDisplayed!=value)
                {
                    _isDisplayed = value;
                    onPropertyChanged("isDisplayed");
                }
            }
        }

        private List<Graphic> _airResourceGraphics;
        public List<Graphic> airResourceGraphics
        {
            get { return _airResourceGraphics; }
            set
            {
                if (_airResourceGraphics!=value)
                {
                    _airResourceGraphics = value;
                    onPropertyChanged("airResourceGraphics");
                }
            }
        }

        private string _returnMessage;
        public string returnMessage
        {
            get { return _returnMessage; }
            set
            {
                if (_returnMessage != value)
                {
                    _returnMessage = value;
                    onPropertyChanged("returnMessage");
                }
            }
        }

        private bool _displayIsChecked;
        public bool displayIsChecked
        {
            get { return _displayIsChecked; }
            set
            {
                if (_displayIsChecked != value)
                {
                    _displayIsChecked = value;
                    onPropertyChanged("displayIsChecked");
                }
            }
        }

        private string _tmpResourceKml;
        private string _tmpKmz;
        
        private const double _maxX = -126.58;
        private const double _minX = -114.21;
        private const double _maxY = 48.18;
        private const double _minY = 39.96;

        private double _latitude;
        private double _longitude;
       
        public ICommand addKmlAffLayerCommand { get { return new AddKmlAffLayerCommand(this); } }
        public ICommand toggleDisplayAff { get { return new ToggleDisplayAffCommand(this); } }

        public void addAff()
        {
            returnMessage = "";
            ofd = new OpenFileDialog();
            ofd.DefaultExt = ".kml";
            ofd.Filter = "AFF KML File (*.KML)|*.kml|AFF KMZ File (*.kmz)|*.kmz";
            ofd.ShowDialog();
            if (ofd.FileName!="")
            {
                path = ofd.FileName;
                status = "Loading";
                affFile(path);
            }
             
        }

        private void affFile(string kmlFilePath)
        {
            affFileObj.Load(kmlFilePath);

            using (XmlReader reader =  XmlReader.Create(affFileObj.BaseURI))
            {
                reader.ReadToFollowing("Url");
                XmlReader urlXml= reader.ReadSubtree();
                urlXml.ReadToFollowing("href");
                resourceUrl = urlXml.ReadString();
            }

            _tmpKmz = Path.GetTempPath().ToString() + "resource.zip";
            _tmpResourceKml = Path.GetTempPath().ToString() + "resource.kml";
            WebClient webDownloader = new WebClient();    
            webDownloader.DownloadFileCompleted += (sender, e) =>
                {
                    using (ZipFile kmz = ZipFile.Read(_tmpKmz))
                        foreach (ZipEntry item in kmz)
                            item.Extract(_tmpResourceKml,ExtractExistingFileAction.OverwriteSilently);
                    status = "refreshing";
                    
                    parseKmlResources();
                };
            webDownloader.DownloadProgressChanged += (sender, e) =>
                {
                    bytesReceivedDisp = e.BytesReceived.ToString() + "kb/";
                    totalBytesDisp = e.TotalBytesToReceive.ToString() + "kb";

                    bytesReceived = Convert.ToDouble(e.BytesReceived);
                    totalBytes = Convert.ToDouble(e.TotalBytesToReceive);
                };
        
            webDownloader.DownloadFileAsync(new System.Uri(resourceUrl), _tmpKmz);
        }

        private void parseKmlResources()
        {
            List<Graphic> graphics = new List<Graphic>();
            var resourceXml = XDocument.Load(_tmpResourceKml + "/resource.kml");
            string xmlNs = "{" + resourceXml.Root.Name.Namespace.ToString() + "}";
            foreach (var placemark in resourceXml.Descendants(xmlNs + "Placemark"))
            {
                
                foreach (var coordinates in placemark.Descendants(xmlNs + "Point"))
                {
                    string[] coordinateCollection = coordinates.Element(xmlNs + "coordinates").Value.ToString().Split(new char[] { ',' });
                    _longitude = Convert.ToDouble(coordinateCollection[0]);
                    _latitude = Convert.ToDouble(coordinateCollection[1]);
                }
                if (_latitude < _maxY && _latitude > _minY)
                {
                    if (_longitude > _maxX && _longitude < _minX)
                    {
                        MobileResource affResource = new MobileResource(placemark.Value.ToString());

                        Graphic airResourceGraphic = new Graphic() { Geometry = new MapPoint(_longitude, _latitude, new SpatialReference(4326)) };
                        airResourceGraphic.Attributes.Add("Callsign", affResource.callsign);
                        graphics.Add(airResourceGraphic);
                    }
                }
            }
            airResourceGraphics = graphics;
            graphicsLayer.GraphicsSource = airResourceGraphics;
            //this is where the if statement will be if the Display button is checked
            File.Delete(_tmpKmz);
            affFile(path);
        }

       


        
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected void onPropertyChanged(string propertyName)
        {
            try
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            catch (Exception)
            {
                //implement a new type of exception to be honest I really don't because when the style template is reloaded it will still populate
            }
        
        }
        #endregion


    }
}
0 Kudos
AnkitaBhatia
New Contributor III
Hi Brian,
Thanks a lot for sharing the code. 🙂
At this point however I am looking at the advantage I would be getting if I move all my data from excel to KML.
Could you please list the advantages or point me to a link that elaborates the same.

Next thing would be the feasibility of using a graphic layer for displaying my data. As of now the client does not have any feature layers or SDE and the expectation is to plot their data, read from the excel on a graphic layer.
According to my analysis there are a couple of disadvantages :
1. Performance overhead of plotting the graphics at runtime.
2. Many tools (including Editor, QueryTask, FeatureDataGrid etc exploit the feature layer). Will I not be able to use their inbuilt functionalities if I plot all my data on a graphics layer.

Kindly suggest if my analysis is correct. If yes, could you point me to resources proving it.
0 Kudos
BrianLocke
Occasional Contributor II
Hmmm well just right up off the bat, ESRI has done a great job with the graphics layer and having it able to place tens of thousands of Graphics very quickly and and things don't seem to miss a beat, also with Graphicssource the collections can be altered and entire collections of thousands seem to just seamlessly change without a hiccup. I am Impressed

One of the concerns is that I am assuming that there is a need to do editing against both the Features and the Attributes, I think that KML and Exc3l are probably not the best ways to do this and there would be ways to run querytask against Graphics but you may be recreating the ball over and over again.  I would have to really know the data, it's use and what the size of it would be.  Sounds like small business not enterprise??

sorry if this is vague let me know if you need clarification
0 Kudos