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

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

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



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



Nessun commento: