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
lunedì 29 giugno 2009
ArcGIS API for Flex 1.2
Etichette:
ArcGIS API Flex 1.2,
geocoding,
routing
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:
Implementazione di IRequestHandler e IRequestHandler2:
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:
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:
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
}
Etichette:
arcgis server,
c#,
soap,
SOE
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
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.
Etichette:
arcgis,
ArcObjects,
IFeatureClassLoad,
LoadOnlyMode
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
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
Etichette:
ArcGIS API Silverlight
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().
sulla parte client richiamiamo il servizio WCF:
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:
Per la parte javascript ho utilizzato la libreria javascript jquery.
Scarica qui il codice della soluzione.
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.
Etichette:
geojson,
jquery,
Linq,
SQL Server 2008,
virtual earth,
wcf
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
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 Patterns—Elements 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
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 Patterns—Elements 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
Etichette:
c#,
Design Patterns GoF
Iscriviti a:
Post (Atom)