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

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

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



sabato 12 dicembre 2009

Bing Maps Silverlight Control v1.0.1

At last the definitive version of Bing Maps Silverlight Control v1.0.1 has been issued.
Here you can download the SDK.
In order to use it you must also have Visual Studio 2008 sp1 and Silverlight 3 Tools for Visual Studio 2008 SP1.

To visualize StreetSide too download dll here

Here you can see a simple example of how to visualize StreetSide, BirdEye and how to add a video on the map ( hold key CRTL and drag a box on the map, the box is the video extent).



using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Maps.MapControl;
using Microsoft.Maps.MapControl.ExtendedModes;
using Microsoft.Maps.MapControl.Navigation;

namespace veslTest
{
    public partial class MainPage : UserControl
    {

        private MapLayer myLayer = null;


        public MainPage()
        {
            InitializeComponent();
            BirdseyeMode.AddModeToNavigationBar(MyMap);
            StreetsideMode.AddModeToNavigationBar(MyMap);

            //Change the mode to Birdseye Mode
            //MyMap.Mode = new BirdseyeMode();

            MyMap.Mode.Center = new Microsoft.Maps.MapControl.Location(34.05159, -118.24239);
            MyMap.Mode = new StreetsideMode();
            MyMap.Heading = 0.0;
            MyMap.Pitch = 12.3;

            myLayer = new MapLayer();
            MyMap.Children.Add(myLayer);

            //MyMap.MouseClick += new EventHandler<MapMouseEventArgs>(MyMap_MouseClick);

            OpacitySlider.Value = 1.0;
            MyMap.MouseDragBox += new EventHandler<MapMouseDragEventArgs>(MyMap_MouseDragBox);

        }
        void MyMap_MouseDragBox(object sender, MapMouseDragEventArgs e)
        {
            e.Handled = true;
            MediaElement video = new MediaElement();


            Location lFrom = MyMap.ViewportPointToLocation(e.FromViewportPoint);
            Location lTo = MyMap.ViewportPointToLocation(e.ViewportPoint);

          //MediaElement video = new MediaElement();
          video.Source = new Uri("http://download.microsoft.com/download/3/6/E/36E181F7-8392-419B-B4BC-A82E88C5348C/Bing%20Maps%20Video.wmv", UriKind.RelativeOrAbsolute);


          double opacity;
          if (double.TryParse(OpacityText.Text, out opacity))
          {
              video.Opacity = opacity;
          }


          video.HorizontalAlignment = HorizontalAlignment.Stretch;
          video.VerticalAlignment = VerticalAlignment.Stretch;
          video.MediaFailed += MediaFailed;


          myLayer.AddChild(video, new LocationRect(lFrom, lTo));



        }








        private void MediaFailed(object sender, ExceptionRoutedEventArgs e)
        {
            //Ignore the error
        }



        private void Button_Click_Rotate(object sender, RoutedEventArgs e)
        {
            RotateMapCommand rotateMapCommand = new RotateMapCommand(true);

            rotateMapCommand.Execute(MyMap);


        }



        private void Button_Click_RemoveAll(object sender, RoutedEventArgs e)
        {
            myLayer.Children.Clear();

        }

        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {

            OpacityText.Text = string.Format("{0:F2}", e.NewValue);
        }


    }
}

xaml:

<UserControl x:Class="veslTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Grid.RowDefinitions>
      <RowDefinition Height="40" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="500"/>
    </Grid.ColumnDefinitions>
    <m:Map CredentialsProvider="YOUR KEY" x:Name="MyMap" Center="34.05159,-118.24239" ZoomLevel="19" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
    <StackPanel Orientation="Horizontal" Opacity="0.7" Grid.Column="1" Grid.Row="0">
      <Button Click="Button_Click_Rotate"  Tag="Rotate" Margin="5">
        <TextBlock>Rotate</TextBlock>
      </Button>
      <Button Click="Button_Click_RemoveAll" Tag="Remove all" Margin="5">
        <TextBlock>Remove all</TextBlock>
      </Button>
      <TextBlock VerticalAlignment="Center">Opacity:</TextBlock>
      <Slider x:Name="OpacitySlider" Minimum="0" Maximum="1" ValueChanged="Slider_ValueChanged" Width="100"></Slider>
      <TextBox x:Name="OpacityText" Text="1" Width="50" Height="25" VerticalAlignment="Center"/>
    </StackPanel>
  </Grid>
</UserControl>











lunedì 23 novembre 2009

Geoprocessing message & log4net in arcgis desktop

Quando eseguiamo un processo di Geoprocessing attraverso gli ArcObjects, possiamo a runtime ricevere i messaggi che il processo stesso genera. Per poter 'catturare' i messaggi possiamo creare una classe che implementa l'interfaccia IGeoProcessorEvents.

public class GPMessageEventHandler : IGeoProcessorEvents
{

    private MessageDetails messageDetails = null;


    public GPMessageEventHandler(MessageDetails messageDetails)
    {
        this.messageDetails = messageDetails;
    }


    public void OnMessageAdded(IGPMessage message)
    {
        this.messageDetails(message);
    }


    public void PostToolExecute(IGPTool tool, IArray values, int result, IGPMessages messages)
    {
    }


    public void PreToolExecute(IGPTool tool, IArray values, int processID)
    {
    }


    public void ToolboxChange()
    {
    }
}

Prima di eseguire il geoprocesso registriamo l'istanza della classe che riceve gli eventi mediante RegisterGeoProcessorEvents.


private static readonly log4net.ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    private static readonly bool isDebugEnabled = log.IsDebugEnabled;

    public static void RunTool(Geoprocessor geoprocessor, IGPProcess process, ESRI.ArcGIS.esriSystem.ITrackCancel trackCancel, MessageDetails messageDetails)
    {
        try
        {
            // Set the overwrite output option to true
            geoprocessor.OverwriteOutput = true;

            IGeoProcessorEvents geoProcessorEvents = new GPMessageEventHandler(messageDetails);
            if (isDebugEnabled)
            {
                log.Debug("RegisterGeoProcessorEvents");
            }
            geoprocessor.RegisterGeoProcessorEvents(geoProcessorEvents);
            if (isDebugEnabled)
            {
                log.Debug("Execute the tool");
            }
            geoprocessor.Execute(process, trackCancel);

            if (isDebugEnabled)
            {
                log.Debug("UnRegisterGeoProcessorEvents");
            }
            geoprocessor.UnRegisterGeoProcessorEvents(geoProcessorEvents);
        }
        catch(Exception ex)
        {
            ExceptionHandler.ThrowException(ex, typeof(Helper));
        }
    }


Nel costruttore della classe, che riceve gli eventi, passiamo il delegato che si occupa di visualizzare i messaggi ( messageDetails ).

Nel nostro caso il delegato è dichiarato nel seguente modo:

public delegate void MessageDetails(IGPMessage data);

e nella windows form, il metodo di tipo MessageDetails, che visualizza i messaggi è:

public void WriteDetails(IGPMessage message)
    {
        // Font font = new Font("Tahoma", 8, FontStyle.Regular);
        // richTextBox1.SelectionFont = font;
        Color color = Color.Black;
        if (message.IsError())
        {
            color = Color.Red;
        }
        else if (message.IsWarning())
        {
            color = Color.Green;
        }
        else if (message.IsAbort())
        {
            color = Color.DarkMagenta;
        }

        rtbDetails.SelectionColor = color;
        rtbDetails.SelectedText = message.Description;
        rtbDetails.SelectionStart = rtbDetails.Text.Length;
        rtbDetails.ScrollToCaret();
        rtbDetails.AppendText(System.Environment.NewLine);
    }

Poichè il controllo di output è di tipo RichTextBox, possiamo formattarlo in funzione del tipo di messaggio (come fa il GeoProcessing degli ArcToolBox).

Volevo aprire una parentesi riguardo alla possibilità di utilizzare log4net come logger per la dll.

Impostiamo il file di appender a runtime:



XmlConfigurator.Configure(new System.IO.FileInfo(string.Format("{0}\\logging.config", codeBase)));
        IAppender appender = log4net.LogManager.GetRepository().GetAppenders()[0];

        FileAppender fileAppender = appender as FileAppender;
        fileAppender.File = Path.Combine(codeBase, "GPExtensionLog.txt");
        fileAppender.ActivateOptions();


e  utilizziamo una classe di handler per le eccezioni:

public static class ExceptionHandler
{
    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    public static void ThrowException(Exception e, Type source, string message)
    {
        log.Error("Exception: " + message);
        log.Error("{" + source + "} " + e.Message + ", StackTrace: " + e.StackTrace);
        throw e;
    }

    public static void ThrowException(Exception e, Type source)
    {
        log.Error("{" + source + "} " + e.Message + ", StackTrace: " + e.StackTrace);
        throw e;
    }
}


per poi utilizzarla:

   geoprocessor.UnRegisterGeoProcessorEvents(geoProcessorEvents);
        }
        catch(Exception ex)
        {
            ExceptionHandler.ThrowException(ex, typeof(Helper));
        }



Scarica qui la soluzione

giovedì 12 novembre 2009

GIS DAY 2009: NicoGIS, PaoloGIS e Studio A&T in diretta!

Solo per comunicarvi che aderisco all'iniziativa di PaoloGIS, tutti i dettagli sul suo blog...

mercoledì 4 novembre 2009

Google encoded polygons da SQL Server 2008

Pubblico un proof of concept per come codificare poligoni o polilinee in google maps leggendo dati da sql server 2008.
In questo link potete trovare l'articolo di Google che spiega algoritmo mentre una spiegazione più approfondita potete trovarla in questi due link Encoding algorithm e Description of encoded polylines di Mark McClure.

Inoltre sempre su Google potete testare direttamente online Interactive Polyline Encoder Utility

Nel progetto che vi ho allegato ho utilizzato il js PolylineEncoder che potete trovare qui.

In sintesi ho tradotto in c# la classe PolylineEncoder per poter creare le polilinee & poligoni anche lato server.

Lato server

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Web.Services;
using Microsoft.SqlServer.Types;

//Author: Domenico Ciavarella
//http://www.studioat.it

namespace GoogleEncode
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
        [WebMethod]
        public static List<List<double []>> GetPolygonEncodeClient()
        {
            List<List<double[]>> pts = new List<List<double []>>();
            using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["GeoConnectionString"].ConnectionString))
            {
                conn.Open();
                string sqlCommandText = "SELECT GEOM FROM LimitiComunali WHERE FID < 20";

                using (SqlCommand sqlCommand = new SqlCommand(sqlCommandText, conn))
                {
                    using (SqlDataReader sdr = sqlCommand.ExecuteReader())
                    {
                        while (sdr.Read())
                        {
                            pts.Add(GetPoints<List<double[]>, double[]>((SqlGeography)(sdr["GEOM"]),(d1,d2) => new double[2]{d1,d2}));
                        }
                    }
                }

            }
            return pts;
        }

        [WebMethod]
        public static Encode[] GetPolygonEncodeServer()
        {
            PolylineEncoder polylineEncoder = new PolylineEncoder();
            IList<Encode> pts = new List<Encode>();

            using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["GeoConnectionString"].ConnectionString))
            {
                conn.Open();
                string sqlCommandText = "SELECT GEOM FROM LimitiComunali WHERE FID < 20";
                using (SqlCommand sqlCommand = new SqlCommand(sqlCommandText, conn))
                {
                    using (SqlDataReader sdr = sqlCommand.ExecuteReader())
                    {
                        while (sdr.Read())
                        {
                            pts.Add(polylineEncoder.DpEncode(GetPoints<List<Point>,Point>((SqlGeography)(sdr["GEOM"]),(d1,d2) => new Point(d1,d2)).ToArray<Point>()));
                        }
                    }
                }
            }
            return pts.ToArray<Encode>();
        }

        public static T GetPoints<T,U>(SqlGeography sqlGeography, Func<double,double,U> ctor) where T :ICollection<U>, new()
        {
            SqlGeography sqlGeographyExterior = null;

            T list = new T();
            if (sqlGeography.NumRings().Value == 1)
            {
                sqlGeographyExterior = sqlGeography;
            }
            else
            {
                sqlGeographyExterior = sqlGeography.RingN(1);
            }

            SqlGeography sqlGeographyCurrent = null;
            for (int i = 1; i <= sqlGeographyExterior.STNumPoints().Value; i++)
            {
                sqlGeographyCurrent = sqlGeographyExterior.STPointN(i);


                list.Add(ctor(sqlGeographyCurrent.Long.Value, sqlGeographyCurrent.Lat.Value));
            }

            return list;
        }


    }
}



Lato client (decommenta PageMethods.GetPolygonEncodeClient o PageMethods.GetPolygonEncodeServer se rispettivamente vuoi codificare lato client o lato server)

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="GoogleEncode._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA"
            type="text/javascript"></script>
<script src ="js/PolylineEncoder.js" type="text/javascript"></script>
<script type="text/javascript">
    var map = null;
    function initialize() {
      if (GBrowserIsCompatible()) {
          map = new GMap2(document.getElementById("map_canvas"));
          var mapControl = new GMapTypeControl();
          map.addControl(mapControl);
          map.addControl(new GLargeMapControl());
          var centerat = new GLatLng(45.52, 7.52);
          map.setCenter(centerat, 10);

          //build encode from client
          PageMethods.GetPolygonEncodeClient(onCompleteGetPolygonEncodeClient, onFailureGetPolygonEncode);

          //build encode from server
          //PageMethods.GetPolygonEncodeServer(onCompleteGetPolygonEncodeServer, onFailureGetPolygonEncode);  
      }
    }

    function onCompleteGetPolygonEncodeServer(result, response, context) {
        var plArray = new Array();

        for (i = 0; i < result.length; i++) {

            var polyline = { color: "#0000ff",
                weight: 3,
                opacity: 0.9,
                points: result[i].EncodedPoints,
                levels: result[i].EncodedLevels,
                numLevels: 18,
                zoomFactor: 2
            };
            Array.add(plArray, polyline);

        }
        var polygon = new GPolygon.fromEncoded({polylines: plArray, color: "#0000ff", opacity: 0.9, fill: true, outline: true });
        map.addOverlay(polygon);

    }





    function onCompleteGetPolygonEncodeClient(result, response, context) {

        var plArray = new Array();
        var polygonEncoder = new PolylineEncoder();
        for (i = 0; i < result.length; i++) {
            var pts = PolylineEncoder.pointsToGLatLngs(result[i]);
            var plJSON = polygonEncoder.dpEncodeToJSON(pts, "#0000ff", 3, 0.9);
            Array.add(plArray, plJSON);

        }

        var polygon = new GPolygon.fromEncoded({ polylines: plArray, color: "#0000ff", opacity: 0.9, fill: true, outline: true });
        map.addOverlay(polygon);

    }
    function onFailureGetPolygonEncode(objError) {
        alert(objError.get_message());
    }

    function ColorRandom() {
        return (Math.round(0xFFFFFF * Math.random()).toString(16) + "000000").replace(/([a-f0-9]{6}).+/, "#$1").toUpperCase();
    }

    </script>
  </head>

  <body onload="initialize()" onunload="GUnload()">
  <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager" runat="server"
       EnablePageMethods="true">
       </asp:ScriptManager>
        <div id="map_canvas" style="width: 800px; height: 600px"></div>
    </form>

  </body>

</html>
Scarica qui la soluzione



sabato 24 ottobre 2009

ArcGIS Javascript API 1.5

E' disponibile la nuova versione di API per ARCGIS javascript.
Mentre per quel che riguarda le estensioni per Google Maps API e Microsoft Virtual Earth non ci sono state modifiche.
In sintesi le novità sono:
- supporto per Firefox 3.5
- supporto per Dojo 1.3.2
- possibilità di modificare il tipo di cursor ( nello specifico utilizzando Map.setMapCursor() )
- possibilità di accedere ai javascript API in modalità HTTPS
- correzione di diversi bugs per migliorare le prestazioni e la stabilità degli ArcGIS JavaScript API

Per dettagli segui il link

martedì 13 ottobre 2009

Geocoding & StreetView Google per ESRI API Silverlight

Pagine aspx dell'applicazione web

<%@ Page="" Language="C#" AutoEventWireup="true" %>
<%@ Register="" Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=YourKey" type="text/javascript"></script>
<script src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="http://ui.jquery.com/latest/ui/effects.core.js" type="text/javascript"></script>
<script src="http://ui.jquery.com/latest/ui/effects.explode.js" type="text/javascript"></script>
<script src="http://ui.jquery.com/latest/ui/ui.core.js" type="text/javascript"></script>
<script src="http://ui.jquery.com/latest/ui/ui.draggable.js" type="text/javascript"></script>
<html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;">
<head runat="server">
<title>Silverlight Google Geocode/StreetView</title>
<script type="text/javascript">
$(document).ready(function() {
$('#txtAddress').keypress(function(e) {
if (e.which == 13) {
$('#btnFindAddress').click();
e.preventDefault();
}
});
});
function runEffect(x,y,divID) {
//run the effect
$("#" + divID).css({ left: x, top: y });
$("#" + divID).effect('bounce');
//set draggable
$("#" + divID).draggable({ cursor: 'crosshair'});
$("#" + divID).draggable('disable');
};
var geocoder;
function FindAddress(address) {
geocoder = new GClientGeocoder();
geocoder.getLocations(address, addAddressToMap);
}
function addAddressToMap(response) {
if (!response response.Status.code != 200) {
alert("No Address found");
} else {
place = response.Placemark[0];
var lon = place.Point.coordinates[0];
var lat = place.Point.coordinates[1];
var address = place.address;
slControl.Content.slApplication.FindIndirizzo(lon, lat, address);
}
}
function streetView(lat, lon, x, y, divID) {
//alert("Message received from Silverlight:" + divID);
var latlng = new GLatLng(lat, lon);
var svp = new GStreetviewClient();
svp.getNearestPanoramaLatLng(latlng,
function(newPoint) {
if (newPoint == null) {
alert("Street View Not Available For This Location");
return;
}
var divMain = document.createElement('div');
divMain.setAttribute("id", divID + "_Contain");
divMain.setAttribute("style", "position:absolute; z-index:1000; height: 325px; width: 300px;background-color:#888888");
var btnDraggable = document.createElement('input');
btnDraggable.setAttribute("id", divID + "_Move");
btnDraggable.setAttribute("type", "button");
btnDraggable.setAttribute("style", "position:relative;z-index:1000;height: 25px; width: 60px;left:5px;top:5px");
btnDraggable.setAttribute("value", "unlock");
btnDraggable.setAttribute("onclick", "var a = $get('" + divID + "_Move');var b = $('#" + divID + "_Contain');if (a.value =='unlock') {a.value = 'lock'; b.draggable('enable');}else{a.value = 'unlock';b.draggable('disable');}");
divMain.appendChild(btnDraggable);
var btnClose = document.createElement('input');
btnClose.setAttribute("id", divID + "_Close");
btnClose.setAttribute("type", "button");
btnClose.setAttribute("style", "position:relative;z-index:1000;height: 25px; width: 60px;left:180px;top:5px");
btnClose.setAttribute("value", "close");
btnClose.setAttribute("onclick", "var a = $get('" + divID + "_Contain');a.style.display='none';");
divMain.appendChild(btnClose);
var divSV = document.createElement('div');
divSV.setAttribute("id", divID);
divSV.setAttribute("style", "position:relative;z-index:1000;height: 290px; width: 290px;left:5px;top:5px");
divMain.appendChild(divSV);
document.forms[0].insertBefore(divMain, $get("controlSL"));
panoramaOptions = { latlng: newPoint };
svp = new GStreetviewPanorama(divSV);
GEvent.addListener(svp, "error", StreetViewError);
var myPov = { yaw: 176.03773913343627, pitch: -0.13590989423507835 };
svp.setLocationAndPOV(latlng, myPov);
runEffect(x, y, divID + "_Contain");
});
}
function StreetViewError(errorCode) {
if (errorCode == 603) {
alert("Error: Flash doesn't appear to be supported by your browser");
return;
}
if (errorCode == 600) {
alert("Street View Not Available For This Location");
return;
}
}
var slControl = null;
function pluginLoaded(sender){
slControl = sender.get_element();
};
</script>
</head>
<body style="height:100%;margin:0;">
<form id="form1" runat="server" style="height:100%;">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<div id ="controlSL" style="height:100%;">
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/saGoogleGeocode.xap" Windowless ="true" OnPluginLoaded="pluginLoaded" MinimumVersion="2.0.31005.0" Width="100%" Height="97%" />
<input id="txtAddress" type="text" />
<input id="btnFindAddress" type="button" value="Find address (Google)" onclick="FindAddress($get('txtAddress').value);" />
</div>
</form>
</body>
</html>


Page.xaml


using System;
using System.Windows.Browser;
using System.Windows.Controls;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
//Domenico Ciavarella www.studioat.it
namespace saGoogleGeocode
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
}
[ScriptableMember()]
public void FindIndirizzo(double lon, double lat, string address)
{
Graphic graphic = new Graphic();
graphic.Symbol = StrobeMarkerSymbol;
graphic.Attributes.Add("Address", address);
MapPoint pt = new MapPoint(lon, lat,new SpatialReference(4326));
graphic.Geometry = pt;
GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
graphicsLayer.ClearGraphics();
graphicsLayer.Graphics.Add(graphic);
MyMap.ZoomTo(pt.Envelope(0.005));
//if you project point
//GeometryService geometryService = new GeometryService("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
//geometryService.ProjectCompleted += GeometryService_ProjectCompleted;
//graphic.Geometry = new MapPoint(lon, lat, new SpatialReference(4326));
//IList<Graphic> graphics = new List<Graphic>() { graphic };
//geometryService.ProjectAsync(graphics, new SpatialReference(3003)); //<---your wkid
}
private void MyMap_MouseClick(object sender, Map.MouseEventArgs e)
{
MapPoint p = e.MapPoint;
string divId = Guid.NewGuid().ToString();
HtmlPage.Window.Invoke("streetView", p.Y, p.X, e.ScreenPoint.X, e.ScreenPoint.Y,divId);
}
}
public static class Utility
{
public static Envelope Envelope(this MapPoint pt, double expand)
{
return new Envelope(pt.X - expand, pt.Y - expand, pt.X + expand, pt.Y + expand);
}
}
}


Scarica qui la soluzione

sabato 3 ottobre 2009

Store IGeometry in SQL server 2008

Problema: supponiamo di avere un web service che crea IGeometry utilizzando ArcGIS Server e di voler esporre il dato geometrico per SQL Server 2008 (Express).


Soluzione: per ottimizzare il passaggio dei dati dal web service al client conviene passarli in wkb (well-known binary). Per questa operazione ci viene incontro un metodo degli ArcObjects: CreateWkbVariantFromGeometry.


Con il seguente codice convertiamo una IGeometry nella rappresentazione wkb.


IPolygon polygon = GetIGeometry();


IGeometryFactory3 geometryFactory = (IGeometryFactory3)serverContext.CreateObject("esriGeometry.GeometryEnvironment");


byte[] polygonWKB = geometryFactory.CreateWkbVariantFromGeometry(polygon) as byte[];



Lato client: creiamo un SqlGeometry con il metodo SQL server 2008 STGeomFromWKB e prima di memorizzare la geometria la validiamo con il metodo MakeValidGeographyFromGeometry della libreria SQL Server Spatial Tools


System.Data.SqlTypes.SqlBytes polygonWKB = new System.Data.SqlTypes.SqlBytes(PolygonWKB);


SqlGeometry sqlGeometry = SqlGeometry.STGeomFromWKB(polygonWKB, 4326);



SqlGeography sqlGeography = Functions.MakeValidGeographyFromGeometry(sqlGeometry);



using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLServerConnectionString"].ConnectionString))


{


conn.Open();


string sqlCommandText = "insert into [YourTable]([Punto],[Poligono]) Values(@pPunto,@pPoligono)";



SqlGeography punto = SqlGeography.Point(lat, lon, 4326);


using (SqlCommand sqlCommand = new SqlCommand(sqlCommandText, conn))


{


sqlCommand.CommandType = CommandType.Text;


sqlCommand.Parameters.Add(new SqlParameter("@pPunto", punto) { UdtTypeName = "Geography" });


sqlCommand.Parameters.Add(new SqlParameter("@pPoligono", sqlGeometry) { UdtTypeName = "Geography" });


sqlCommand.ExecuteNonQuery();



}



}