2013-07-03 2 views
2

Un peu sur l'application;SqlGeography.STIntersection() renvoie même quand je sais qu'il n'y a pas d'intersection

L'application permet à l'utilisateur de dessiner et enregistrer des polygones sur des cartes Bing API WPF. Le code qui nous intéresse est de trouver la météo d'un point dans le polygone ou non. La fonction suivante parcourt simplement le LocationCollection du polygone sur la carte Bing et crée un SqlGeography object (OpenGisGeographyType.Polygon) qui est une instance d'un polygone.

Ensuite, nous convertissons le clic de la souris en SqlGeography object (OpenGisGeographyType.Point) par latitude et longitude et utilisons le SqlGeography.STIntersection pour trouver si notre point se trouve dans le polygone.

Comme vu dans l'image, même lorsque le point est en dehors du polygone, SqlGeography.STIntersection renvoie toujours un point d'intersection. (Vous pouvez le dire dans l'image comme j'ai mis une étiquette à "Within Delivery Area" ou "Customer our of Area" en fonction de ce que la fonction polygonSearch() retourné

Le bon exemple dans l'image a les résultats attendus quand un emplacement est testé dans le polygone

l'exemple de gauche dans l'image contient les résultats inattendus - qui indique qu'un point est dans un polygone, quand il est clairement pas

enter image description here

NOTES.:

  • I Utilisez SqlGeography (myShape) pour mettre les formes sur la carte, donc je sais que la forme est construite avec des verticies appropriées.
  • J'utilise SqlGeography (myPoint) pour mettre la broche sur la carte, donc je sais que la broche est testée aux verticies correctes.
    • UNIQUEMENT SUR CE MANQUE POLYGONES GRANDS

Ci-dessous je donne la peice de code qui crée le polygone en mémoire, ainsi que convertit l'événement click de souris pour lat, la longitude. (J'ai inclus les verticies polygonales dans les commentaires afin que cela puisse être regardé sans avoir besoin de l'API bing, il suffit de remplacer la boucle for par les commentaires ci-dessus) Bien que vous ayez besoin de Microsoft.SqlServer.Types.dl l pour créer les objets SqlGeography. Est gratuit avec SQL Express 2008, et se trouve dans C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies

public bool polygonSearch2(LocationCollection points, double lat, double lon) 
    { 
    SqlGeography myShape = new SqlGeography(); 
    SqlGeographyBuilder shapeBuilder = new SqlGeographyBuilder(); 

    // here are the verticies for the location collection if you want to hard code and try 
    //shapeBuilder.BeginFigure(47.4275329011347, -86.8136038458706); 
    //shapeBuilder.AddLine(36.5102408627967, -86.9680936860962); 
    //shapeBuilder.AddLine(37.4928909385966, -80.2884061860962); 
    //shapeBuilder.AddLine(38.7375329179818, -75.7180936860962); 
    //shapeBuilder.AddLine(48.0932596736361, -83.7161405610962); 
    //shapeBuilder.AddLine(47.4275329011347, -86.8136038458706); 
    //shapeBuilder.EndFigure(); 
    //shapeBuilder.EndGeography(); 

    // Here I just loop through my points collection backwards to create the polygon in the SqlGeography object 
    for (int i = points.Count - 1; i >= 0; i--) 
    { 
     if (i == 0) 
     { 
      shapeBuilder.AddLine(points[i].Latitude, points[i].Longitude); 
      shapeBuilder.EndFigure(); 
      shapeBuilder.EndGeography(); 

      continue; 

     } 
     if (i == points.Count - 1) 
     { 

      shapeBuilder.SetSrid(4326); 
      shapeBuilder.BeginGeography(OpenGisGeographyType.Polygon); 
      shapeBuilder.BeginFigure(points[i].Latitude, points[i].Longitude); 

      continue; 
     } 
     else 
     { 
      shapeBuilder.AddLine(points[i].Latitude, points[i].Longitude); 
     } 
    } 

    myShape = shapeBuilder.ConstructedGeography; 

    // Here I am creating a SqlGeography object as a point (user mouse click) 
    SqlGeography myPoint = new SqlGeography(); 
    SqlGeographyBuilder pointBuilder = new SqlGeographyBuilder(); 
    pointBuilder.SetSrid(4326); 
    pointBuilder.BeginGeography(OpenGisGeographyType.Point); 
    // Should pass, which it does 
    // Lat: lat = 43.682110574649791 , Lon: -79.79005605528323 
    // Should fail, but it intersects?? 
    // Lat: 43.682108149690094 , Lon: -79.790037277494889 
    pointBuilder.BeginFigure(lat, lon); 
    pointBuilder.EndFigure(); 
    pointBuilder.EndGeography(); 


    myPoint = pointBuilder.ConstructedGeography; 


    SqlGeography result = myShape.STIntersection(myPoint); 

    if (result.Lat.IsNull) 
     return false; 
    else 
     return true; 



} 

Toute aide tout est très apprécié, je commence à conduire mes noix de patron avec ce problème>. <

Cela peut-il avoir quelque chose à voir avec le SRID?

+0

Est-ce que cela retourne toujours vrai ou seulement quand il est proche - mais-encore-dehors? –

+0

@ ta.speot.est seulement quand proche mais toujours dehors – clamchoda

+0

'Ceci échoue seulement après le zoom'. Voulez-vous dire qu'après avoir zoomé sur la carte et ajouté un marqueur, le résultat incorrect est renvoyé? Ce n'est pas qu'un marqueur à l'intérieur du polygone est rendu à l'extérieur du polygone lorsque l'image est agrandie, n'est-ce pas? – Tim

Répondre

0

J'ai corrigé ceci en convertissant tout mon polygone lat/long en un objet Point à l'écran en utilisant la fonction LocationToViewPortpoint, ainsi que le point que je teste pour l'intersection, et utilise les valeurs X et Y au lieu de lat/long dans mon STIntersects.

Questions connexes