2012-07-27 21 views
8

Me gustaría guardar un círculo en un campo de geografía sql-server 2008, usando C#.Crear un polígono-círculo SqlGeography a partir de un centro y radio

En C# Tengo una latitud, una longitud y un radio, pero no puedo encontrar la manera de calcular el polígono que representaría el círculo y crear un SqlGeography a partir de él.

me han tratado de la función siguiente para crear el polígono:

private List<Coordinate> getCirclePoints(Coordinate center, int radius, int speed) //speed 1: draws 360 sides, 2 draws 180 etc... 
    { 
     var centerLat = (center.Latitude * Math.PI)/180.0; //rad 
     var centerLng = (center.Longitude * Math.PI)/180.0; //rad 
     var dist = (float)radius/6371.0;    //d = angular distance covered on earth's surface 
     var circlePoints = new List<Coordinate>(); 
     for (int x = 0; x <= 360; x += speed) 
     { 
      var brng = x * Math.PI/180.0;   //rad 
      var latitude = Math.Asin(Math.Sin(centerLat) * Math.Cos(dist) + Math.Cos(centerLat) * Math.Sin(dist) * Math.Cos(brng)); 
      var longitude = ((centerLng + Math.Atan2(Math.Sin(brng) * Math.Sin(dist) * Math.Cos(centerLat), Math.Cos(dist) - Math.Sin(centerLat) * Math.Sin(latitude))) * 180.0)/Math.PI; 
      circlePoints.Add(new Coordinate((latitude * 180.0)/Math.PI, longitude)); 
     } 
     return circlePoints; 
    } 

Y luego tratar de convertir esta List<Coordinate> a una cadena, apta para:

 var s = "POLYGON((" + string.Join(",", points.ConvertAll(p => p.Longitude + " " + p.Latitude).ToArray()) + "))"; 
     var poly = SqlGeography.STPolyFromText(new System.Data.SqlTypes.SqlChars((SqlString)s), 4326); 

Pero siempre se queja el polígono tiene que ser en un solo hemisferio, donde estoy seguro de que es el caso.

¿Estoy en el camino correcto? ¿Hay alguna otra forma (más simple) de hacer esto?

Respuesta

19

OK, encontré la respuesta por mi cuenta. El truco es crear un punto

var point = SqlGeography.Point(latitude, longitude, 4326); 

A continuación, crear un buffer alrededor del punto

var poly = point.BufferWithTolerance(radiusInMeter, 0.01, true); //0.01 is to simplify the polygon to keep only a few sides 

entonces se podría simplemente crear un SqlCommand y añadir el polígono como parámetro:

var param = new SqlParameter(@"Polygon", poly); 
param.UdtTypeName = "Geography"; 
command.Parameters.Add(param); 

Esperanza eso ayudará a alguien más en el futuro!

+0

muy apreciado señor, ¡gracias! – EdGs

+1

Esto fue muy útil, gracias por esto. Después de leer un poco más, pensé que valdría la pena agregar que el valor de tolerancia de .01 dará como resultado un polígono de 33 puntos (círculo geométrico sql estándar). Si se permite algún error, se puede usar un valor mayor. Estoy esperando que mi radio esté entre 5 y 50 metros, por lo que estoy usando 3 para mi valor de tolerancia para mejorar la eficiencia. –

+0

Gracias a su comentario, realicé algunas pruebas y cambié mi tolerancia a 0.08, que parece dar un polígono de 16 lados para radios pequeños. – Johann

Cuestiones relacionadas