-----------------------------------

Acquista i software ArcGIS tramite Studio A&T srl, rivenditore autorizzato dei prodotti Esri.

I migliori software GIS, il miglior supporto tecnico!

I migliori software GIS, il miglior supporto tecnico!
Azienda operante nel settore GIS dal 2001, specializzata nell’utilizzo della tecnologia ArcGIS e aderente ai programmi Esri Italia Business Network ed Esri Partner Network

-----------------------------------



lunedì 29 giugno 2009

ArcGIS API for Flex 1.2

E' disponibile da maggio 2009 la nuova versione delle API ArcGIS for Flex (versione 1.2)

Le novità principali sono il routing di ArcGIS Server, il mapping ed il geocoding di Virtual Earth (richiede autenticazione) e nel renderer la custom SymbolFunction che facilità la classificazione unique values e class breaks per la tematizzazione della mappa. Tra le utilities spicca l'helper per proiettare da WKID (well-known ID) 4326 (WGS84 lat/log del geocoding Virtual Earth) al WKID 102113 (Web Mercator usato dal Virtual Earth Tiled)

Samples

Sample Viewer

Basic Routing

Virtual Earth base maps

Virtual Earth geocoder

martedì 23 giugno 2009

SOE via SOAP

Aspettando la 9.4 10.0 dove l'implementazione di una SOE (Server Object Extension) via SOAP e REST sarà molto più agevole, è possibile fornire le funzionalità di una propria SOE via SOAP.

La nostra classe SOE dovrà implementare le interfacce IRequestHandler e IRequestHandler2:



[AutomationProxy(true), ClassInterface(ClassInterfaceType.None), GuidAttribute("8C37367E-DF95-4441-AD77-A3DF68877966")]
public class LayoutSOE : ServicedComponent, ILayout, IServerObjectExtension, ILogSupport, IObjectConstruct, IRequestHandler, IRequestHandler2
{



Implementazione di IRequestHandler e IRequestHandler2:

#region IRequestHandler Membri di
 
            public byte[] HandleBinaryRequest(ref byte[] request)
            {
                throw new NotImplementedException();
            }
 
            public string HandleStringRequest(string Capabilities, string request)
            {
 
                ESRI.ArcGIS.esriSystem.IXMLStream requestXmlStream = new ESRI.ArcGIS.esriSystem.XMLStreamClass();
                requestXmlStream.LoadFromString(request);
 
                ESRI.ArcGIS.esriSystem.IMessage requestMessage = new ESRI.ArcGIS.esriSystem.MessageClass();
                requestMessage.ReadXML(requestXmlStream as ESRI.ArcGIS.esriSystem.IStream);
 
                string responseHeader = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
                responseHeader += "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" ";
                responseHeader += "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ";
                responseHeader += "xmlns:tns=\"http://www.esri.com/schemas/ArcGIS/9.3\">";
                responseHeader += "<soap:Body>";
 
                string response = null;
 
                if (requestMessage.Name == "GetLayoutSOERequest")
                {
                    ESRI.ArcGIS.esriSystem.IXMLSerializeData requestParameters = requestMessage.Parameters;
                    int idxTemplate = requestParameters.Find("Template");
                    string template = requestParameters.GetString(idxTemplate);
                    int idxFormat = requestParameters.Find("Format");
                    string format = requestParameters.GetString(idxFormat);
 
                    int idxMapDescription = requestParameters.Find("MapDescription");
                    //IMapDescription p =
                    //(IMapDescription)requestParameters.GetObject(
                    //idxMapDescription, "http://www.esri.com/schemas/ArcGIS/9.3", "MapDescription");
 
                    string mapDescriptionSerialize = requestParameters.GetString(idxMapDescription);
                    System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
                    xmlDocument.LoadXml(mapDescriptionSerialize);
                    System.Xml.XmlElement xmlElement = xmlDocument.DocumentElement;
                    string soapSerializedValueObject = xmlElement.OuterXml;
                    ESRI.ArcGIS.esriSystem.IXMLSerializerAlt comXmlSerializerAlt = new
                      ESRI.ArcGIS.esriSystem.XMLSerializerAlt();
                    IMapDescription mapDescription = (IMapDescription)
                      comXmlSerializerAlt.LoadFromString(soapSerializedValueObject,
                      "MapDescription", "http://www.esri.com/schemas/ArcGIS/9.3");
 
 
 
                    int idxPropertyChanges = requestParameters.Find("PropertyChanges");
                    //IPropertySet prp =
                    //(IPropertySet)requestParameters.GetObject(
                    //idxPropertyChanges, "http://www.esri.com/schemas/ArcGIS/9.3", "PropertySet");
 
                    string propertySetSerialize = requestParameters.GetString(idxPropertyChanges);
                    xmlDocument = new System.Xml.XmlDocument();
                    xmlDocument.LoadXml(propertySetSerialize);
                    xmlElement = xmlDocument.DocumentElement;
                    soapSerializedValueObject = xmlElement.OuterXml;
                    comXmlSerializerAlt = new
                      ESRI.ArcGIS.esriSystem.XMLSerializerAlt();
 
                    IPropertySet propertySet = (IPropertySet)
                      comXmlSerializerAlt.LoadFromString(soapSerializedValueObject,
                      "PropertySet", "http://www.esri.com/schemas/ArcGIS/9.3");
 
                    try
                    {
 
                        ILayout layout = this;
                        ILayoutAttribute layoutAttribute = layout.ExportLayout(mapDescription, template, propertySet, format);
                        response = responseHeader;
                        response += "<tns:GetLayoutSOEResponse>";
                        response += string.Format("<Url>{0}</Url>", layoutAttribute.Url);
                        response += string.Format("<HasError>{0}</HasError>",layoutAttribute.HasError.ToString().ToLower());
                        response += "</tns:GetLayoutSOEResponse>";
                        response += "</soap:Body></soap:Envelope>";
                    }
                    catch (Exception ex)
                    {
                        response = responseHeader;
                        response += "<tns:GetLayoutSOEResponse>";
                        response += string.Format("<Url>{0}</Url>", ex.Message);
                        response += "<HasError>true</HasError>";
                        response += "</tns:GetLayoutSOEResponse>";
                        response += "</soap:Body></soap:Envelope>";
                        return response;
                    }
                }
                return response;
 
 
            }
 
            #endregion
 
            #region IRequestHandler2 Membri di
 
 
            public byte[] HandleBinaryRequest2(string Capabilities, ref byte[] request)
            {
                throw new NotImplementedException();
            }
 
            #endregion


Nella SOE deserializzamo la stringa SOAP in oggetti ArcObjects con IXMLSerializerAlt


Nella cartella C:\Program Files (x86)\ArcGIS\XmlSchema creiamo il file WSDL con lo stesso nome della SOE:



File LayoutSOE.wsdl:

<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:e="http://www.esri.com/schemas/ArcGIS/9.3" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.esri.com/schemas/ArcGIS/9.3">
  <types>
    <xs:schema targetNamespace="http://www.esri.com/schemas/ArcGIS/9.3" xmlns="http://www.esri.com/schemas/ArcGIS/9.3">
      <xs:element name="GetLayoutSOERequest">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="MapDescription" type="xs:string" />
            <xs:element name="Template" type="xs:string" />
            <xs:element name="PropertyChanges" type="xs:string" />
            <xs:element name="Format" type="xs:string" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="GetLayoutSOEResponse">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Url" type="xs:string" />
            <xs:element name="HasError" type="xs:boolean" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
  </types>
  <message name="GetLayoutSOERequestIn">
    <part name="parameters" element="e:GetLayoutSOERequest" />
  </message>
  <message name="GetLayoutSOERequestOut">
    <part name="parameters" element="e:GetLayoutSOEResponse" />
  </message>
  <portType name="LayoutSOEPort">
    <operation name="GetLayoutSOERequest">
      <input message="e:GetLayoutSOERequestIn" />
      <output message="e:GetLayoutSOERequestOut" />
    </operation>
  </portType>
  <binding name="LayoutSOEBinding" type="e:LayoutSOEPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <operation name="GetLayoutSOERequest">
      <soap:operation soapAction="" style="document" />
      <input>
        <soap:body use="literal" />
      </input>
      <output>
        <soap:body use="literal" />
      </output>
    </operation>
  </binding>
  <service name="#NAME#">
    <port name="LayoutSOEPort" binding="e:LayoutSOEBinding">
      <soap:address location="#URL#" />
    </port>
  </service>
</definitions>


Creiamo un servizio ArcGIS Server, abilitiamo la SOE e il web access per consentire una connessione internet.

Testiamo il wsdl:




Ora testiamo la SOE creando una web application basata sul servizio creato precedentemente. Nei web references puntiamo alla SOE:



I values ArcGIS Server saranno convertiti in stringhe SOAP:

using System;
using System.Collections.Generic;
using System.Web;
using ESRI.ArcGIS.ADF.Web.UI.WebControls;
using ESRI.ArcGIS.ADF.Web.DataSources;
using ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools;
using ESRI.ArcGIS.esriSystem;
using System.Text;
using ESRI.ArcGIS.ADF.ArcGISServer;
using PrintSOAP;
 
 
public class PrintTest : IMapServerCommandAction
{
 
    #region IServerAction Membri di
 
    public void ServerAction(ToolbarItemInfo info)
    {
 
 
        string ResourceName = "NameResource";
        string TemplateName = "NameTemplate";
 
        ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap =
            (ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)info.BuddyControls[0];
 
        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality agsMapFunctionality =
            (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality)adfMap.GetFunctionality(ResourceName);
 
 
        ESRI.ArcGIS.ADF.ArcGISServer.MapDescription agsSoapMapDescription = agsMapFunctionality.MapDescription;
 
        //Serialize value object into SOAP string
        Type valueType = agsSoapMapDescription.GetType();
        System.Xml.Serialization.XmlSerializer xmlSerializer =
          new System.Xml.Serialization.XmlSerializer(valueType);
 
        System.Text.StringBuilder stringBuilder = new StringBuilder();
        System.IO.StringWriter stringWriter = new System.IO.StringWriter(stringBuilder);
        xmlSerializer.Serialize(stringWriter, agsSoapMapDescription);
 
        string soapSerializedValueObjectMapDescription = stringBuilder.ToString();
 
 
 
        #region Set Property PDF
        ESRI.ArcGIS.ADF.ArcGISServer.PropertySet prp = new ESRI.ArcGIS.ADF.ArcGISServer.PropertySet();
        PropertySetProperty[] parameters = new PropertySetProperty[13];
 
        PropertySetProperty property = new PropertySetProperty();
        property.Key = "Resolution";
        property.Value = 300;
        parameters.SetValue(property, 0);
 
        property = new PropertySetProperty();
        property.Key = "LayoutScale";
        property.Value = 5000.0;
        parameters.SetValue(property, 1);
 
        property = new PropertySetProperty();
        property.Key = "MarkerSymbolsToPolygons";
        property.Value = false;
        parameters.SetValue(property, 2); 
 
        property = new PropertySetProperty();
        property.Key = "EmbedFonts";
        property.Value = true;
        parameters.SetValue(property, 3); 
 
        property = new PropertySetProperty();
        property.Key = "CompressVectorGraphics";
        property.Value = false;
        parameters.SetValue(property, 4);
 
        property = new PropertySetProperty();
        property.Key = "ImageCompression";
        property.Value = "esriExportImageCompressionDeflate";
        parameters.SetValue(property, 5);
 
        property = new PropertySetProperty();
        property.Key = "ExportMeasureInfo";
        property.Value = false;
        parameters.SetValue(property, 6);
 
        property = new PropertySetProperty();
        property.Key = "ExportPDFLayersAndFeatureAttributes";
        property.Value = "esriExportPDFLayerOptionsNone";
        parameters.SetValue(property, 7);
 
        property = new PropertySetProperty();
        property.Key = "ExportPictureSymbolOptions";
        property.Value = "esriPSORasterizeIfRasterData";
        parameters.SetValue(property, 8);
 
        property = new PropertySetProperty();
        property.Key = "ExportColorspaceSettings";
        property.Value = "esriExportColorspaceRGB";
        parameters.SetValue(property, 9);
 
        property = new PropertySetProperty();
        property.Key = "ResampleRatio";
        property.Value = "esriRasterOutputNormal";
        parameters.SetValue(property, 10);
 
        property = new PropertySetProperty();
        property.Key = "ResolutionScreen";
        property.Value = 96;
        parameters.SetValue(property, 11);
 
        property = new PropertySetProperty();
        property.Key = "Graphics";
        property.Value = null;
        parameters.SetValue(property, 12);
 
        prp.PropertyArray = parameters;
        #endregion
 
 
        valueType = prp.GetType();
        xmlSerializer =
          new System.Xml.Serialization.XmlSerializer(valueType);
        stringBuilder = new StringBuilder();
        stringWriter = new System.IO.StringWriter(stringBuilder);
        xmlSerializer.Serialize(stringWriter, prp);
        string soapSerializedValueObjectPropertySet = stringBuilder.ToString();
 
        PrintSOAP.Test_Layoutsoe p = new Test_Layoutsoe();
 
 
        bool hasError;
        string urlPDF = p.GetLayoutSOERequest(soapSerializedValueObjectMapDescription, TemplateName, soapSerializedValueObjectPropertySet, "pdf", out hasError);   
 
 
    //    p.GetLayoutSOERequestCompleted += new PrintSOAP.GetLayoutSOERequestCompletedEventHandler(getLayoutSOERequestCompletedEventHandler);
    //    p.GetLayoutSOERequestAsync(soapSerializedValueObjectMapDescription, TemplateName, soapSerializedValueObjectPropertySet, "pdf");
    //
    }
 
    //public void getLayoutSOERequestCompletedEventHandler(object sender, GetLayoutSOERequestCompletedEventArgs e)
    //{
 
    //    string s = e.Result;
    //    //e.HasError
    //}
 
    #endregion
}

sabato 20 giugno 2009

Load-only mode

IFeatureClassLoad è un'interfaccia opzionale per FeatureClass ArcSDE e per FeatureClass e Table file geodatabase. Abilitando la modalità 'Load-Only' miglioriamo le prestazioni di caricamento dei dati.
Con questa modalità disabilitiamo l'aggiornamento degli indici spaziali e degli indici sugli attributi (questi ultimi solo per il file geodatabase) mentre si esegue un'operazione di inserimento di rows o features. Gli indici verranno ricostruiti una volta che si disabilita la modalità Load-Only.
Quando una feature class o una tabella è in modalità load-only altre applicazioni non possono lavorare su questi dati, pertanto occorre acquisire un lock esclusivo dello schema sulla tabella o feature class tramite l'interfaccia ISchemaLock

Qui potete vedere un esempio di caricamento dati in una feature class in modalità Load-Only
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.esriSystem;
using System.IO;
using ESRI.ArcGIS.Geodatabase;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.ADF;
using System.Diagnostics;
 
namespace caCursors
{
    class Program
    {
        static void Main(string[] args)
        {
 
            Arguments CommandLine = new Arguments(args);
 
            if ((args.Length == 0)  (CommandLine["help"] != null)  (CommandLine["h"] != null))
            {
                Console.WriteLine("The arguments to the utility are:");
                Console.WriteLine("caCursors [-hhelp] [-lloadOnlyMode]");
                Console.WriteLine("caCursors -l true");
                Console.WriteLine("Press Enter to continue...");
                Console.ReadLine();
                return;
 
            }
 
            bool loadOnlyMode;
 
            if ((CommandLine["loadOnlyMode"] != null)  (CommandLine["l"] != null))
            {
                string sloadOnlyMode = CommandLine["l"] ?? CommandLine["loadOnlyMode"];
                bool result;
                if (!Boolean.TryParse(sloadOnlyMode, out result))
                {
                    Console.WriteLine("Parametro loadOnlyMode non corretto. Indicare: {0} o {1}", Boolean.TrueString, Boolean.FalseString);
                    return;
                }
                loadOnlyMode = result;
            }
            else
            {
                Console.WriteLine("Indicare il parametro loadOnlyMode: caCursors -l ({0} or {1})", Boolean.TrueString, Boolean.FalseString);
                return; 
            }
 
 
            #region Licensing
 
            IAoInitialize aoInitialize = new AoInitializeClass();
            esriLicenseStatus licenseStatus = aoInitialize.Initialize(esriLicenseProductCode.esriLicenseProductCodeArcInfo);
            if (licenseStatus != esriLicenseStatus.esriLicenseCheckedOut)
            {
                Console.WriteLine("Licenza ArcInfo non trovata, errore numero: {0}", licenseStatus);
                return;
            }
            #endregion
 
 
            Console.WriteLine("Cancellazione gdb ...");
            if (Directory.Exists("Comuni.gdb"))
                Directory.Delete("Comuni.gdb", true);
 
            Console.WriteLine("Copia gdb per test ...");
 
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
 
            IWorkspaceName sourceWorkspaceName = new WorkspaceNameClass { PathName = @"..\..\Data\Comuni.gdb", WorkspaceFactoryProgID = "esriDataSourcesGDB.FileGDBWorkspaceFactory" };
 
            IWorkspaceName copiedWorkspaceName = null;
            workspaceFactory.Copy(sourceWorkspaceName, Environment.CurrentDirectory, out copiedWorkspaceName);
 
 
            IName copiedName = (IName)copiedWorkspaceName;
            IWorkspace workspace = (IWorkspace)copiedName.Open();
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
 
 
 
            IFeatureClass featureClass = featureWorkspace.OpenFeatureClass("Comuni");
 
            IWorkspace workspaceInput = ShapefileWorkspaceFromPath(@"..\..\Data");
            IFeatureClass featureClassInput = ((IFeatureWorkspace)workspaceInput).OpenFeatureClass("Comuni");
 
            Console.WriteLine("Inserimento dati in gdb ...");
            InsertCursor(workspace, featureClass, featureClassInput, loadOnlyMode);
 
 
 
            aoInitialize.Shutdown();
        }
 
 
        private static void InsertCursor(IWorkspace workspace, IFeatureClass featureClass, IFeatureClass featureClassInput, bool LoadOnlyMode)
        {
 
 
 
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
 
            IFeatureClassLoad featureClassLoad = (IFeatureClassLoad)featureClass;
 
            ISchemaLock schemaLock = null;
            if (LoadOnlyMode)
            {
                featureClassLoad.LoadOnlyMode = LoadOnlyMode;
                schemaLock = (ISchemaLock)featureClass;
            }
 
 
            IWorkspaceEdit workspaceEdit = (IWorkspaceEdit)workspace;
            workspaceEdit.StartEditing(true);
            workspaceEdit.StartEditOperation();
 
 
            using (ComReleaser comReleaser = new ComReleaser())
            {
 
                IFeatureCursor featureCursor = featureClass.Insert(true);
                comReleaser.ManageLifetime(featureCursor);
 
 
                IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();
                comReleaser.ManageLifetime(featureBuffer);
 
                IFeatureCursor featureCursorInput = featureClassInput.Search(null, true);
                comReleaser.ManageLifetime(featureCursorInput);
 
                try
                {
                    IFeature feature = null;
                    while ((feature = featureCursorInput.NextFeature()) != null)
                    {
 
 
 
                        featureBuffer.Shape = feature.ShapeCopy;
                        featureBuffer.set_Value(2, feature.get_Value(2)); //istat_new (campo con indice)
                        featureBuffer.set_Value(5, feature.get_Value(5)); //comune (campo con indice)
 
                        //for (int i = 2; i < 8; i++)
                        //    featureBuffer.set_Value(i, feature.get_Value(i));
 
 
 
                        featureCursor.InsertFeature(featureBuffer);
                    }
 
 
                    featureCursor.Flush();
 
 
                    workspaceEdit.StopEditOperation();
                    workspaceEdit.StopEditing(true);
 
                }
                catch (COMException)
                {
 
                    workspaceEdit.AbortEditOperation();
                    workspaceEdit.StopEditing(false);
                }
            }
 
            if (LoadOnlyMode)
            {
                featureClassLoad.LoadOnlyMode = false;
                schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
 
            }
 
 
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
 
 
            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}",
                ts.Hours, ts.Minutes, ts.Seconds,
                ts.Milliseconds);
            Console.WriteLine(elapsedTime);
            Console.WriteLine("Premere invio ...");
            Console.Read();
        }
 
 
 
        public static IWorkspace ShapefileWorkspaceFromPath(String path)
        {
            Type factoryType = Type.GetTypeFromProgID(
              "esriDataSourcesFile.ShapefileWorkspaceFactory");
            IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)
              Activator.CreateInstance(factoryType);
            return workspaceFactory.OpenFromFile(path, 0);
        }
    }
}
 
Scarica qui la soluzione.

venerdì 19 giugno 2009

ArcGIS API for Microsoft Silverlight /WPF Release Candidate

In attesa del Viewer per Silverlight (previsto in coincidenza con la UC americana) è stata rilasciata la release candidate (build 255 - giugno 2009).

Qui potete vedere l'elenco delle novità di questa release.

Tra le novità è stato aggiunto il RoutingTask per il supporto delle operazioni di routing fornite dai servizi di ArcGIS Server Network Analyst.

Qui potete vedere l'SDK in azione.

Esempio OpenStreetMap

lunedì 15 giugno 2009

SQL Server 2008 - Virtual Earth

Nella versione 2008 di SQL Server sono stati introdotti due nuovi tipi di dati: Geometry e Geography.
Per capire la differenza tra i due tipi di dati potete trovare la documentazione su MSDN.

Vediamo ora come caricare uno shapefile da ArcGIS Desktop (mediante l'extension Data Interoperability) in SQL Server 2008.

Per questo esempio potete anche utilizzare la versione SQL Server 2008 Express SP1 e il tool di Morten Nielsen.

Come si può vedere dalla figura qui sotto, dagli Arctoolbox si seleziona 'Quick Export' e dalla lista dei formati si seleziona Microsoft SQL Server Spatial. Lo shapefile è stato preventivamente proiettato in wgs84.








Una volta caricati, è possibile visualizzarli in Virtual Earth. In questo momento non abbiamo un metodo diretto per poterli visualizzare poichè gli output da SQL Server 2008 sono il WKT e il GML e il formato nativo che nei client .NET si traduce nei tipi .NET SqlGeometry e SqlGeography; mentre Virtual Earth necessita di GeoRSS, KML, xml personalizzato da processare con javascript personalizzato o stringhe Javascript da passare ad eval().


In questo esempio creiamo una stored procedure (GetLimiteComunale) che chiamiamo tramite un servizio WCF utilizzando Linq to SQL. La stored procedure restituisce la versione GML (nell'esempio eliminiamo la parte di tag di apertura e chiusura) della feature richiamata. Nel servizio utilizziamo poi l'utility GeoRssUtils per pubblicare i dati su Virtual Earth.







In Visual Studio 2008 trasciniamo le stored procedure sul design della classe Linq to SQL



e questo è il metodo nel servizio WCF

public SyndicationFeedFormatter GetLimiteComunale(string id)
    {
        var geoData = new GeoRssData("GetLimiteComunale", "Seleziona comune");
        using (var db = new SpatialDataDataContext())
        {
            var result = db.GetLimiteComunale(int.Parse(id)).First();
            geoData.AddPolygon(result.Name, string.Format("Comunità Montana:{0}", result.Comunità_Montana), result.Polygon);
        }
 
        return new Rss20FeedFormatter(GeoRssFeedBuilder.GetFeed(geoData));
    }


sulla parte client richiamiamo il servizio WCF:

$(document).ready(function() {
 
    map = new VEMap("myMap");
    map.LoadMap();
    map.SetCenterAndZoom(new VELatLong(45.132, 7.438), 10);
 
    $("#btnIdGetLimiteComunale").click(function() {
        var request = "SpatialData.svc/GetLimiteComunale/" + $("#txtIdComune").val();
 
        var layer = new VEShapeLayer();
        var layerSpec = new VEShapeSourceSpecification(
                                    VEDataType.GeoRSS,
                                    request,
                                    layer);
 
        map.ImportShapeLayerData(layerSpec);
    });



Stessa cosa facciamo con la stored procedure GetLimitiComunaliLimitrofi. In questo caso viene mostrato come utilizzare le funzioni spaziali messe a disposizione da SQL Server (vedi http://msdn.microsoft.com/en-us/library/bb895266.aspx ). Nello specifico selezioniamo i comuni confinanti con il comune cercato.




Con la terza stored procedure (GetLimiteComunaleJSON) restituiamo il dato al servizio WCF in formato WKT e sul client inviamo i dati in formato GeoJSON che verranno poi processati mediante l'helper javascript per VE.


Sul client:
$("#btnIdAddPointGeoJSON").click(function() {
        var v = new VEGeoJSON(map);
        $.ajax({ type: "POST",
            url: "SpatialData2.svc/GetLimiteComunaleJSON",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: '{"id":"' + $("#txtIdComune").val() + '"}',
            success: function(data) {
 
                var geoJSON = eval('(' + data.d + ')');
                v.addGeoJSON(geoJSON);
            }
        });



Per la parte javascript ho utilizzato la libreria javascript jquery.

Scarica qui il codice della soluzione.

martedì 2 giugno 2009

ArcGIS JavaScript API 1.4

E' stata rilasciata la versions 1.4 di ArcGIS JavaScript API e ArcGIS JavaScript Extension per Google Maps API. La versione 1.4 di ArcGIS JavaScript Extension per Microsoft Virtual Earth sarà disponibile a presto.
Come al solito per utilizzare le nuove versioni occorre aggiornare il tuo riferimento allo script con "v=1.4", ad esempio: http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1.4.
Nuove funzionalità in in ArcGIS JavaScript API 1.4:
Routing con ArcGIS network analysis services
Supporto per mappe e geocoding forniti da Microsoft Virtual Earth
Supporto per multipli graphics layers
Class breaks e unique value renderers
Supporto per Dojo 1.3.1
prestazioni migliorate in Internet Explorer
Bug fixes

Vedi su What's New in Version 1.4 of the ArcGIS JavaScript API la lista completa dei miglioramenti. C'è anche un documento What's New per Google Maps API extension. La principale funzionalità introdotto con la versione 1.4 per ArcGIS JavaScript extensions per Google Maps API e Virtual Earth è il routing con ArcGIS network analysis services.

Vedi gli esempi live sulle funzionalità di routing:
Find routes with barriers and multiple stops
Get driving directions
Find a route

Da segnalare per il routing con Google

Design Patterns

Quando cerchi di immaginare come creare una nuova funzionalità intuisci cosa devi fare e quali oggetti servono ma hai la sensazione che ci sia un modo più elegante di scrivere il tuo programma.
In effetti, difficilmente scriverai un codice senza avere in mente uno schema di che cosa fa il codice e di come le varie parti del codice interagiscono.
Più questo schema costituisce un "insieme organico", più ti sentirai sicuro di aver sviluppato la miglior soluzione al problema.
In un certo senso una soluzione elegante sarà anche riutilizzabile e manutenibile.
I ricercatori si sono interessati ai design patterns per soddisfare il bisogno di soluzioni eleganti ma semplici e riutilizzabili. Infatti, essi sono un modo conveniente di riutilizzare codice orientato agli oggetti tra programmi e tra programmatori. L'idea è semplice: catalogare interazioni comuni tra oggetti che i programmatori hanno frequentemente trovato utili.
Un dei pattern più citati è il framework MVC (Model-View-Controller), che ha diviso il problema dell'interfaccia utente in tre parti.
Il riferimento sull'argomento è Design PatternsElements of Reusable Software di Gamma, Helm, Johnson, e Vlissides chiamati le gang dei quattro (GoF): il testo ebbe un notevole impatto sugli utenti che cercavano di capire come servirsi dei design patterns. Esso infatti descrivere i 23 pattern più comuni ed utili e spiega come applicarli.

Introduzione ai design pattern