Este artigo foi traduzido por máquina.

SQL Server e MapPoint

Fazendo o MapPoint 2010 e o SQL Server Spatial trabalharem juntos

Eric Frost

Baixe o código de exemplo

Após Bing Maps, duas das tecnologias geoespaciais mais visíveis da Microsoft são o Microsoft MapPoint 2010 e a funcionalidade espacial no SQL Server 2008 R2. No entanto, mesmo que o SQL Server é um armazenamento ideal para dados geoespaciais e MapPoint faz um bom geoespaciais visualizador, comunicando-se entre os dois é não quase tão simples quanto poderia ser.

Esse artigo demonstrará como ler objetos de polígono de ponto e do SQL Server e processá-los em MapPoint. Também demonstraremos como gravar pontos e polígonos em SQL Server usando o Entity Framework 4. 0 incluído no Visual Studio 2010.

Para fins de ilustração, usará a “ Beef de popular AL ” baseados em Chicago do restaurante locais da empresa e áreas comerciais hipotético. Na modelagem e análise de varejo, áreas comerciais podem ser definidas usando vários parâmetros em podem ser usadas para objetivos diferentes. Normalmente, estão definidas como a região menor em torno de uma loja que contém áreas que atendam a um limite específico — por exemplo, onde 50 por cento ou 75 por cento dos clientes em tempo real ou de trabalho. Todas as áreas comerciais usadas neste artigo foram geradas usando o recurso de fuso do MapPoint criar Drivetime, portanto, elas representam uma área do comércio hipotético com base nos levando a tempos.

Como uma cadeia com menos de alguns locais de dúzias de Beef de AL é uma empresa relativamente pequena, mas os mesmos conceitos e técnicas que podem ser aplicadas para varejistas de grandes com milhares de locais e em outros aplicativos e indústrias.

O dataset “ Beef de popular AL ” (como um script SQL) e o código de exemplo estão disponíveis para download em code.msdn.microsoft.com/mag201009Spatial de .

Enquanto isso não é um artigo técnico excessivamente cobrindo hermética aspectos da linguagem ou a tecnologia mais recente, ele serve como um prático como para um casamento útil das tecnologias comuns da Microsoft. Alguns obstáculos incluem a incapacidade do Entity Framework compreende diretamente objetos da área geográfica e o requisito de espacial do SQL Server de polígonos, seja no sentido anti-horário, que não é necessária para o MapPoint. Espera-se, neste artigo ajudará os desenvolvedores experientes, mesmo que podem estar relutantes pular para o setor de geoespaciais por falta de experiência anterior e ao mesmo tempo mostrar MapPoint desenvolvedores como aproveitar com êxito o SQL Server 2008 R2.

Configurando o banco de dados

Para acompanhar as amostras de código incluídas aqui, baixe o script SQL e executá-la contra o SQL Server para configurar o banco de dados e objetos. Os dados são armazenados em um banco de dados do SQL Server chamado “ corporações ” e incluem uma tabela, um modo de exibição e um procedimento armazenado. Beef locais de AL são armazenados em uma tabela chamada “ locais ” (consulte do Figura 1).

image: The Table and View Included in the Sample Database

Figura 1 de A tabela e o modo de exibição incluídas no banco de dados de exemplo

Isso inclui endereços ’ lojas, atributos (por exemplo, é um drive-in?) e um tipo de dados local de ponto de localização geográfica. Os polígonos da área de comércio hipotético também são armazenados na tabela “ locais ”, em um campo chamado TradeArea usando o tipo de dados geography.

O modo de exibição vLocations expõe os campos de geography ponto e o polígono em tipos de dados que podem ser entendidos e ler na estrutura de entidades.

O campo de geography ponto é decomposto em campos de latitude e longitude e passado de volta para o cliente como um campo varbinary. Isso ocorre porque o Entity Framework não é possível lidar com tipos de dados geography diretamente, mas ele pode manipular campos varbinary. Posteriormente, o aplicativo pode converter essas back em objetos de geography.

Aqui está o uspAddLocation do procedimento armazenado, que, como o nome sugere, é usado para inserir novos locais do MapPoint para o SQL Server:

CREATE VIEW [dbo].[vLocations]
AS
SELECT LocID,Location.Long As Longitude,
       Location.Lat As Latitude,
       CAST(Location AS VARBINARY(MAX)) AS Location,
       Locations.TradeArea.STAsText() As TradeAreaWKT,
       CAST(TradeArea AS VARBINARY(MAX)) AS TradeArea
FROM Locations

Vai voltamos a isso mais tarde.

Como configurar o aplicativo

Nosso projeto é um aplicativo c# Windows Forms que incorpore o controle do MapPoint. O controle está incluído com o MapPoint 2010 e a versão completa do MapPoint 2010 deve estar instalada para que ele esteja disponível. Podem-se navegar registros usando botões para percorrer os registros e exibir o armazenamento e a sua área de negócio. Armazenamentos também podem ser selecionados, clicando no ícone do pino da loja. O formulário também possui uma caixa de seleção para exibir a área de negócio como um hull convexo e um botão para adicionar novos locais. Por padrão, o aplicativo mostra o polígono é armazenado no banco de dados (consulte do Figura 2).

image: The Al’s Beef App, Showing the Chicago Heights Store and Territory as Defined in the Database

De Beef de O Al App, mostrando o armazenamento de alturas de Chicago e região, como definido no banco de dados, a Figura 2

Se a caixa de seleção do modo de exibição comercial área como convexo Hull for definida, uma linha (hull convexo) é disposta ao redor da área do comércio semelhante a uma faixa de borracha em torno do polígono de disposição (consulte do Figura 3).

image: The Chicago Heights Store, with a Convex Hull Wrapped Around the Territory Shown in Figure 2

Do Armazenamento de alturas de Chicago, com um Hull convexo empacotada em todo o território mostrado na Figura 2, a Figura 3

Antes que podemos implementar a exibição de mapa, precisamos adicionar objetos de dados de entidade que apontam para a tabela de banco de dados e o modo de exibição. Para estabelecer os objetos de dados de entidade, clique com o botão direito no aplicativo no Visual Studio Solution Explorer e vá para Add | New Item | Visual C# itens | modelo de dados de entidade ado.net. Clique em Add e escolha Generate no banco de dados. In the Choose Your Database Objects dialog, select the table Locations and the view vLocations. Após você clicar em ' Concluir ', o assistente irá criar os objetos e gerar o código necessário para se conectar ao banco de dados.

Para adicionar o controle de 2010 MapPoint para o Windows Form, é necessário primeiro adicionar o componente de controle COM o MapPoint para a caixa de ferramentas do Visual Studio. COM não é a tecnologia mais fashionable, mas ela continua a ser uma parte importante do ecossistema Windows. Muitos aplicativos, incluindo o MapPoint, apenas implementam uma API através de uma interface COM e COM suporte a partir de dentro do Visual Studio não vai desaparecer a qualquer momento em breve.

Abra a caixa de ferramentas do Visual Studio e, na seção geral, clique com o botão direito e selecione Escolher itens. Vá para a guia componentes COM e selecione Microsoft MapPoint controle 17. 0. 17. 0 Do controle MapPoint refere-se para o MapPoint 2010 (América do Norte ou Europa). Versões mais antigas do MapPoint (2002 em diante) também podem ser usadas, mas as alterações de nome secundários (por exemplo, a barra de ferramentas e o nome do símbolo identificador), será necessárias.

Nos assemblies AxInterop.MapPoint e o Interop.MapPoint, defina a propriedade tipo de interoperabilidade de incorporação para false e o local da cópia para o controle do MapPoint True.The podem agora ser arrastado para o formulário e usado dentro do aplicativo.

Inicializando a forma de mapa: Carregando o MapPoint

A forma de mapa declara diversas variáveis de membro, incluindo a conexão de banco de dados com o Entity Framework, uma lista de informações da loja e uma lista paralela de informações de geográficos ’ armazena que serão lidos do modo de exibição. A variável curLoc mantém controle sobre a identificação de armazenamento atual dentro do aplicativo e objMap é usado para fazer referência a objeto de mapa MapPoint do controle, como mostrado aqui:

namespace AlsBeef
{
 public partial class Map : Form
 {
  CorporateEntities db;
  List<Location> locationList;
  List<vLocation> vlocationList;
  int curLoc = -1;    // <0 indicates 'not set'
  MapPoint.Map objMap;
  MapPoint.Symbol objSymb;
  ...

Quando o formulário é criado, o método CreateNewMapObject é chamado para inicializar o controle de mapa e abra um novo mapa usando o modelo de mapa padrão América do Norte. As barras de ferramentas são definidas, objMap é definido e pontos de interesse é ligado desligado assim como para não truncar o mapa (consulte do Figura 4). “ Pontos de interesse ” são que MapPoint casas, restaurantes e predefinidos teatros, por exemplo.

De criação de um formulário, a Figura 4

public Map()
{
 InitializeComponent();
 CreateNewMapObject();
}


private void CreateNewMapObject()
{
  MPctrl.NewMap(GeoMapRegion.geoMapNorthAmerica);
  object barObj = "advanced";
  MPctrl.Toolbars.get_Item(refbarObj).Visible = true;
  MPctrl.Toolbars.LargeToolbarButtons = false;
  objMap = MPctrl.ActiveMap;
  // Make sure all points of interest are turned off
  objMap.PlaceCategories.Visible = MapPoint.GeoTriState.geoFalse;
}

O método do formulário carga preenche as listas de armazenamento de informações. O locationList contém todas as informações de que não geográficas regulares e vloc ­ ationList lê os campos geográficos como transformados pelo modo de exibição de banco de dados:

private void Map_Load(object sender, EventArgs e)
{
 db = new CorporateEntities();
 locationList = new List<Location>();
 vlocationList = new List<vLocation>();

 ObjectQuery<Location> locationQuery =
  db.Locations;
 ObjectQuery<vLocation> vlocationQuery =
  db.vLocations;

 locationList = locationQuery.ToList();
 vlocationList = vlocationQuery.ToList();

 InitMapSymb();
 InitMapPins();
 SetLocation(0);
}

As duas últimas linhas efetivamente iniciar o aplicativo ao inicializar o mapa. Adicione um pino para cada local de armazenamento (InitMapPins) e posicionar os controles de formulário e o mapa para apontar para os dados para o primeiro local de armazenamento (SetLocation).

Adicionando anotações para o mapa

As coisas ficam mais interessantes no método InitMapPins:

private void InitMapPins()
  {
    MapPoint.Pushpin objPin = null;
    for (int i = 0; i < locationList.Count;
     i++)
    {
     MapPoint.Location objLoc =
      objMap.GetLocation(vlocationList[i].
Latitude.Value,
      vlocationList[i].Longitude.Value);
     objPin = objMap.AddPushpin(objLoc,   
      locationList[i].Name);
     objPin.Symbol = 145; // Red fork and knife
                         // (food, restaurant)
   }
  }

Um loop através de locationList, podemos recuperar os valores de latitude e longitude que foram calculados e expostos pelo modo de exibição. Eles são usados para criar objetos do MapPoint Location, o que são usados para criar o mapa de pinos (pino MapPoint objetos). O nome da loja é usado para a propriedade PushpinName, que será posteriormente usada para pesquisar e posicionar o mapa. As anotações são representadas com o símbolo de pino do MapPoint restaurante vermelho interno (símbolo # 145). Uma lista completa de símbolos internos do MapPoint 2010 pode ser encontrada em mapping-tools.com/info/pushpins/pushpins_2010.shtml de . Esta página também contém links para listas de anotações para versões anteriores do MapPoint.

Posicionar-se no registro atual e adicionando Polygons para o mapa

Novos registros são selecionados e exibida usando os métodos IncDecLocation e SetLocation. IncDecLocation simplesmente se aplica a um incremento (cnt) para a posição atual (curLoc) e passa essa nova posição do registro para SetLocation:

private void IncDecLocation(int cnt = 0)
{
 // Apply the increment/decrement, wrapping around if necessary
 int newLoc = (curLoc + cnt + locationList.Count) % locationList.Count;

 SetLocation(newLoc);
}

A rotina de SetLocation é a força de trabalho do aplicativo. SetLocation seleciona uma nova posição do registro e exibe-os no mapa. SetLocation também remove o realce do pino anterior (se houver) e limpa todos os polígonos anterior de área de comércio do mapa (consulte do Figura 5).

De rotina TheSetLocation É a força de trabalho do aplicativo, a Figura 5

private void SetLocation(int newLoc)
{
  MapPoint.Pushpin objPin = null;

  // Unhighlight previous pushpin
  If (curLoc>= 0)
  {
    objPin = (MapPoint.Pushpin)
     objMap.FindPushpin(locationList[curLoc].Name);
    objPin.Highlight = false;
  }

  // Clear all previous shapes
  while(objMap.Shapes.Count> 0)
  {
    objMap.Shapes[1].Delete();
  }
 

  // Set the new location
  curLoc = Math.Min( Math.Max(newLoc,0), locationList.Count-1);

  objPin = (MapPoint.Pushpin)
   objMap.FindPushpin(locationList[curLoc].Name);
  objMap.Location = objPin.Location;

...

A próxima seção se torna um pouco confusa. Em primeiro lugar, o aplicativo verifica o status da caixa de seleção do modo de exibição comercial área como convexo Hull. Se não tiver sido definida, leva a seqüência de caracteres de texto conhecido (WKT) que define o polígono e passá-lo para o método RenderPolygon personalizado para ser analisado e processado como um polígono no mapa.

Se a caixa de seleção tiver sido definida, ela recebe varbinary objeto do polígono território e converte-os para um objeto de geography usando o método BinaryReader e a classe System.IO.MemoryStream. STConvexHull é um dos métodos que acompanham o SQL Server 2008;Ele permite modificar instâncias de dados geography ou geometria. STConvexHull, em particular, funciona apenas com tipos de dados geometry. As diferenças entre a geometria do SQL Server e os tipos de dados geography é abordado extensivamente em outro lugar, mas por ora, considere que dados geometry são definidos em um plano (2D Euclidean) cartesiano plano, enquanto os dados da área geográfica são projetados para a superfície de terra spheroidal usando um sistema de coordenadas esférico (referência, projeção, meridiano e unidade de medida).

A área de trade é armazenada no banco de dados com um tipo de campo de localização geográfica e, em seguida, convertida em um varbinary pelo modo de exibição. Isso precisa ser lido em um objeto de geography, que pode ser convertido em um objeto geometry para executar o método STConvexHull.

Devido às pequenas áreas em que está sendo abordadas, os cálculos realizados por STConvexHull no objeto geometry (planar) são praticamente as mesmas causaria o hull convexo tinha sido calculada para o objeto de geography spheroidal real.

Na próxima parte SetLocation, a área do comércio original é desenhada como uma linha preta fina e o hull convexo é processado como uma linha vermelha mais espessa. O código é mostrado no do Figura 6.

De desenho a área do comércio original e o Hull convexo, a Figura 6

...
// Draw trade area
if (checkBox1.Checked == false)
{
 RenderPolygon(vlocationList[curLoc].TradeAreaWKT);
}
else
{
  // Need to add C:\Program Files\Microsoft SQL
  // Server\100\SDK\Assemblies\Microsoft.SqlServer.Types.dl
  // to references
  SqlGeographyTradeAreaGeog = new SqlGeography();
  using (var stream = new
   System.IO.MemoryStream(vlocationList[curLoc].TradeArea))
  {
   using (var rdr = new System.IO.BinaryReader(stream))
   {
    TradeAreaGeog.Read(rdr);
   }
  }
  SqlGeometry TAConvexHullGeom = new SqlGeometry();
  TAConvexHullGeom =  
   SqlGeometry.STPolyFromText(TradeAreaGeog.STAsText(), 4326);
  TAConvexHullGeom = TAConvexHullGeom.STConvexHull();
  RenderPolygon(TradeAreaGeom.ToString(), 3355443, 0); // Gray80
  RenderPolygon(TAConvexHullGeog.ToString());
}
...

Portanto, essa seqüência de caracteres WKT aparência e o que RenderPolygon faz com ele? Você já viu os resultados (em 2 de figuras de e 3). Let’s mergulhar de cabeça para a parte interna.

WKT é um formato padrão do OGC (Open geoespaciais Consortium) para formatar os dados de vetor geoespaciais na forma de texto. Uma seqüência de caracteres de polígono WKT aparência (muito abreviado):

POLYGON ((-111.918823979795 33.6180476378649, -111.91810682416 33.6096635553986,
 -111.911686453968 33.6078672297299, -111.907403888181 33.599476357922, 
-111.907403888181 33.6060674674809, -111.903121406212 33.6060674674809))

A palavra “ POLÍGONO ” antecede uma lista de coordenadas que são circundados por dois conjuntos de parênteses. Pares de coordenadas individuais são separados por vírgulas. Nós usamos o método MapPoint AddPolyLine para desenhar o polígono no mapa e adicioná-lo à coleção MapPoint Shapes. Isso leva a uma matriz de objetos do MapPoint Location como um parâmetro. Convertendo a cadeia de caracteres WKT para uma matriz de objetos de localização requer meia dúzias de linhas de código. RenderPolygon realiza isso pela colocação de prefixo “ POLÍGONO ” e parênteses antes de dividir a seqüência de caracteres em coordenadas usando o separador de vírgula. As coordenadas individuais, em seguida, são analisadas em pares de dobras (longitude, latitude) são usadas para criar objetos do MapPoint Location. A matriz resultante dos objetos de localização é então passada para AddPolyline para criar o novo polígono.

RenderPolygon usa parâmetros adicionais para a espessura de linha e cor (consulte do Figura 7).

A Figura 7 do Método TheRenderPolygon

private void RenderPolygon(string polystring, 
 int forecolor = 128, int weight = 3)
{
  polystring = polystring.Replace("POLYGON ((", "");
  polystring = polystring.Replace("))", "");
  string[] stringList = polystring.Split(',');
  MapPoint.Location[] objLoc = 
   new MapPoint.Location[stringList.Count()];
  for (int i = 0; i <stringList.Count(); i++)
  {
   string[] coords = stringList[i].Trim().Split(' ');
   objLoc[i] = objMap.GetLocation(Convert.ToDouble(coords[1]),  
    Convert.ToDouble(coords[0]), 0);
  }
  MapPoint.Shape objShape;
  objShape = objMap.Shapes.AddPolyline(objLoc);
  objShape.Line.ForeColor = forecolor;
  objShape.Line.Weight = weight;
}

Um RenderPolygon mais completa poderá ter parâmetros adicionais para estarem ou não a forma será preenchida, a cor de preenchimento, nome de uma forma (uma seqüência interno pode ser atribuída às formas) e o zOrder (para posicionar a forma na frente ou atrás de estradas e outras formas).

Desenho e a anotação podem ser colocados em um mapa MapPoint pelo usuário e de um programa. O MapPoint oferece suporte a um total de 40 cores diferentes para esta anotação. Embora a interface de programação é exibido dar suporte a cores RGB (16,777,216 diferentes) 3 bytes padrão, na verdade, que esses números simplesmente fornecem uma maneira útil para especificar a cor a ser usada. As 40 cores suportadas pelo MapPoint podem ser vistas em mapping-tools.com/info/pushpins/colors.shtml de .

Historicamente, essa limitação ajudou com eficiência de atualização da imagem, mas atualmente ele principalmente auxilia mapa clareza, ajudando a garantir que as cores são diferentes.

Temos agora venha para a parte final da SetLocation (consulte do Figura 8).

A Figura 8 da parte final de SetLocation

...
// Reset zoom level
   objMap.Altitude = 30;
   objPin.Highlight = true;

   Double distance;
   distance = 
     NearestLocation(curLoc) * 0.000621371192; //convert to miles

   label1.Text = "ID: " + locationList[curLoc].LocID.ToString();
   label2.Text = locationList[curLoc].Name + " - " +  
     locationList[curLoc].Format;
   label3.Text = locationList[curLoc].Address + ", " + 
     locationList[curLoc].City + ", " + locationList[curLoc].State;
   label4.Text = "Distance to next closest store: " + 
     String.Format("{0:#,0.0}", distance) + " miles";

  }

private double NearestLocation(int curLoc)
{

 SqlGeography AllLocations = new SqlGeography();
  SqlGeography CurLocation = new SqlGeography();
  for (int i = 0; i <locationList.Count; i++)
  {
    SqlGeography TempLocation = new SqlGeography();
    using (var stream = new 
     System.IO.MemoryStream(vlocationList[i].Location))
   { 
     using (var rdr = new System.IO.BinaryReader(stream))
     {
       TempLocation.Read(rdr);
     }
   }
   if (i == curLoc)
   {
     CurLocation = TempLocation;
   }
   else
   {
     AllLocations = AllLocations.STUnion(TempLocation);
   }
  }
  return (Double)AllLocations.STDistance(CurLocation); //meters
}

Isso realça o pino de novo, define o nível de zoom (usando o objeto de mapa de altitude de propriedade), relata as informações da loja (a partir do conjunto de locationList) e a distância até o local de armazenamento mais próximo.

Essa distância é calculada pelo NearestLocation. Isso percorre os locais e usa o método STUnion espacial do SQL Server para combinar os pontos de localização geográfica em uma instância MultiPoint de geography usando. A exceção é o local de armazenamento atual for ignorado, caso contrário, a distância deve ser sempre zero milhas! O aplicativo, em seguida, usa o método STDistance para calcular a distância em metros entre o local de armazenamento atual e a instância MultiPoint de geography usando a. STDistance relata a distância até um MultiPoint como a mais curta distância até qualquer ponto do componente dentro do MultiPoint.

O botão para adicionar um novo local de site remove os polígonos trade área do mapa e, em seguida, simplesmente altera o ponteiro do mouse para um cursor de quatro pontas:

private void button1_Click(object sender, EventArgs e)
{
  // Clear all previous shapes
  while(objMap.Shapes.Count > 0)
  {
    objMap.Shapes[1].Delete();
  }
  MPctrl.MousePointer = MapPoint.GeoPointer.geoPointerCrosshair;
}

Para lidar com eventos do MapPoint, o formulário requer um manipulador de eventos definido no formulário do designer. Os eventos podem ser adicionados usando o formulário designer ou adicionado manualmente para Map.Designer.cs. Manipuladores são adicionados para dois dos eventos MapPoint: SelectionChange e BeforeClick, conforme mostrado no do Figura 9.

A Figura 9 de Adicionando manipuladores de eventos do MapPoint

// 
// MPctrl
// 
this.MPctrl.Enabled = true;
this.MPctrl.Location = new System.Drawing.Point(13, 13);
this.MPctrl.Name = "MPctrl";
this.MPctrl.OcxState = 
  ((System.Windows.Forms.AxHost.State)
  (resources.GetObject("MPctrl.OcxState")));
this.MPctrl.Size = new System.Drawing.Size(674, 389);
this.MPctrl.TabIndex = 0;
this.MPctrl.SelectionChange += 
  new AxMapPoint._IMappointCtrlEvents_SelectionChangeEventHandler
 (this.MPctrl_SelectionChange);
this.MPctrl.BeforeClick += 
  new AxMapPoint._IMappointCtrlEvents_BeforeClickEventHandler
  (this.MPctrl_BeforeClick);

O evento SelectionChange é usado para detectar se o usuário tiver selecionado um pino. Isso é usado para mover o registro atual para registro deste pino. A Figura 10 mostra a implementação do manipulador de eventos.

A Figura 10 de implementação de um manipulador de evento SelectionChange

private void MPctrl_SelectionChange(object sender,  
 AxMapPoint._IMappointCtrlEvents_SelectionChangeEvent e)

{
  // Has the user just selected a pushpin?
if (e.pNewSelection is MapPoint.Pushpin)
  {
    MapPoint.Pushpin ppin = e.pNewSelection as MapPoint.Pushpin;

    // Find the corresponding location object, and select it
    for (int iloc = 0; iloc < locationList.Count; iloc++)
    {
      if (locationList[iloc].Name == ppin.Name)
      { // Found it: select, and move to it
        SetLocation(iloc);
        break;
      } 
    } 
  } 
}

Isso verifica se o objeto recém-selecionado é, na verdade, um pino. Em seguida, realizamos uma pesquisa simples por meio do locationList local para um registro coincidente. O MapPoint anotações podem ter nomes duplicados, para que esse código pressupõe que todos os registros de local (e, portanto, pinos) têm nomes exclusivos. Além disso, você deve comparar coordenadas geográficas nas situações em que isso não pode ser considerado.

Manipulador de eventos BeforeClick do mapa é usado na funcionalidade “ adicionar o novo local de armazenamento ”. O manipulador verifica se o ponteiro do mouse é um fio de retículo — ou seja, o usuário está tentando inserir um novo local do site. Ele permite que o MapPoint manipular o evento de clique se o ponteiro não é uma cruz. Se o ponteiro do mouse é um fio de retículo, o programa intercepta a ação de clique e adiciona um novo alfinete no local do ponteiro do mouse usando o símbolo de vermelho do restaurante. Neste ponto, para simplificar as coisas, em vez de ter o empate na área comercial do usuário, o programa usa o método de MapPoint AddDrivetimeZone para gerar uma área hipotético comerciais (viagem-baseada em tempo) em torno do novo site.

O intuito de obter esta forma para o SQL Server, a forma pela primeira vez é decomposta em vértices, que são convertidos em um polígono definição WKT (texto). Isso será gravado para o SQL Server.

Para passar o polígono e o ponto para o SQL Server e atualizar as colunas de Geografia, não podemos usar os normais compatíveis com o Entity Framework procedimentos armazenados, porque não há suporte para o tipo de dados geography. No entanto, porque Entity Framework 4. 0 agora oferece suporte para a execução arbitrária de procedimentos armazenados, é possível importar o procedimento armazenado e executá-la como uma função normal.

Esse código configura os parâmetros e, em seguida, executa usp ­ procedimento AddLocation armazenado:

object[] parameters =
{   
  new SqlParameter("Latitude",objLoc.Latitude),
  new SqlParameter("Longitude",objLoc.Longitude),
  new SqlParameter("PolyWKT",PolyWKT)
};

var retValue = db.uspAddLocation(objLoc.Longitude, 
 objLoc.Latitude, PolyWKT);

Por último, essa rotina redefine o mapa (CreateNewMapObject), repetirá a consulta da lista de locais do banco de dados (InitMapPins) e seleciona o novo armazenamento do registro atual (SetLocation):

// Re-query and re-initialize map
 ObjectQuery<Location> locationQuery = db.Locations;
 ObjectQuery<vLocation> vlocationQuery = db.vLocations;
 locationList = locationQuery.ToList();
 vlocationList = vlocationQuery.ToList();
 objMap.Saved = true;
 CreateNewMapObject();
 InitMapSymb();
 InitMapPins();
 SetLocation( locationList.Count – 1 );
 e.cancel = true;
}

E.cancel=true linha;impede que o MapPoint processamento adicional do evento click. O procedimento armazenado de uspAddLocation segue (consulte do Figura 11).

A Figura 11 da uspAddLocation procedimentos armazenados

CREATE PROCEDURE [dbo].[uspAddLocation]
@Longitude FLOAT,
@Latitude FLOAT,
@PolyWKT NVARCHAR(MAX)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
SET NOCOUNT ON;

DECLARE @NewLocID int = 0
SELECT @NewLocID = MAX(LocID)+1 FROM Locations

DECLARE @NewPoly geography
SET @NewPoly = geography::STPolyFromText(@PolyWKT,4326)

INSERT INTO Locations(LocID,Name,Address,City,State,Format,Location,TradeArea)
VALUES(@NewLocID, 'New Location ' + CAST(@NewLocID As varchar(3)), '123 Main',   
 'Anywhere', 'ST', 'Food', geography::Point(@Latitude,@Longitude,4326), 
 @NewPoly)

SELECT @NewLocID AS NewLocID

END

Você pode ver uma nova instância de geography e a variável que está sendo criado para o polígono antes da instrução INSERT, ao passo que o ponto de local é criado através do método do ponto de dentro do método INSERT. O método é válido.

O código de manipulação de eventos em do Figura 12 lida com botões “ anteriores ” e “ próximos ”, a caixa de seleção hull convexo e o fechamento do formulário — isso conclui o aplicativo.

A Figura 12 de preenchimento do aplicativo

private void prev_Click(object sender, EventArgs e)
{
  IncDecLocation(-1);
}

private void next_Click(object sender, EventArgs e)
{
  IncDecLocation(1);
}

private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
  IncDecLocation();
}

private void Map_FormClosing(object sender, FormClosingEventArgs e)
{
  db.Dispose();
  MPctrl.ActiveMap.Saved = true;
}

Visualizando e editando visualmente os dados de geoespaciais do SQL Server

Este artigo abordou muita Terra, mas ele demonstra um aplicativo completo de ponta a ponta com o SQL Server, mostrando como transmitir dados de entrada e saída usando SQL Server espacial e métodos do MapPoint para exibir e editar informações do mundo real.

Os princípios mostrados aqui podem ser feitos mais. Manter uma cópia local dos dados garante a rápida mapa atualizações, mas não seria prático para grandes conjuntos de dados. Nessas situações, os dados devem ser obtidos em cada registro por registro, o ideal é que um mecanismo de armazenamento em cache.

O MapPoint é capaz de algumas operações geoespaciais úteis (por exemplo, o cálculo de fuso horário de unidade), mas não tem muitas das operações geoespaciais esperadas de um GIS completo. Aqui estamos utilizam duas dessas operações, STConvexHull e STDistance, de extensões de espacial do SQL Server. Outras funções avançadas disponíveis nas extensões espaciais incluem a possibilidade de medir o tamanho e a extensão das características geográficas, bem como a localização de uniões e interseções de polígonos. Essas funções podem ser usadas para criar um aplicativo de gerenciamento sofisticado de região. Isso poderia combinar as regiões ou localizar sobreposições onde um armazenamento de será cannibalizing o negócio de outro.

Da mesma forma, poderiam ser aproveitadas forças do MapPoint. O MapPoint é capaz de geocodificação off-line. Usa o nosso exemplo dinates de ­ coor existentes, mas o geocoder MapPoint poderia ser usado para localizar endereços de ruas em vez disso. O MapPoint também vem com um número de bancos de dados demográficos em município, CEP e níveis de lote de censo. Esses dados podem ser plotados em um mapa de armazenamento, permitindo a fácil comparações sejam feitas — por exemplo, como armazenamento de vendas se comparam às populações locais e os níveis de lucros e perdas.

Olhando adiante, espacial do SQL Server é provável que tenha um gerativo avanço com a próxima versão do SQL Server, o produto do MapPoint tem sido aproveitando um renascimento de desenvolvimento de novos e recursos com as duas últimas versões e isso é definido para continuar. Além disso, o Entity Framework é provável que continue a adicionar suporte a novos tipos de campo, incluindo tipos de dados espaciais, que devem melhorar a comunicação entre o MapPoint e o SQL Server. Juntas, essas tecnologias de formam uma plataforma em evolução robusta e poderosa para desenvolvimento de aplicativos de mapeamento.

Eric Frost é um MVP da Microsoft e o desenvolvedor de aplicativos de negócios especializado em GIS/mapeamento aplicativos. Ele gerencia a ativa Microsoft mapeamento tecnologia fórum mapforums.com e pode ser contatado pelo eric.frost@mp2kmag.com de .

Richard Marsden é um MVP da Microsoft e o desenvolvedor freelance software. Ele vende um número de extensões do MapPoint no mapeamento tools.com de e opera o site da GeoWeb guru de geowebguru.com .

Graças aos seguintes especialistas técnicos para revisão deste artigo: Bob Beauchemin , De Ed Katibah e de Amar Nityananda