2012-11-27 92 views
0

免責聲明:我不是GIS人。必應地圖線多邊形交集

我們正在嘗試使用DotSpatial庫來計算線多邊形交集,然後在WPF Bing Maps控件中顯示該交集。出於某種原因,任何在EW方向上不完全筆直的交叉點都會從Bing中的原始線向下移動。我認爲這是一個投影問題,因爲當我們顯示投影到WGS1984的DotSpatial控件中的所有內容時,不會發生移位。

要重新放置在XAML代碼下面的地圖窗口的後面:

using Microsoft.Maps.MapControl.WPF; 
using System.Windows; 
using System.Windows.Media; 
using DotSpatial.Data; 
using DotSpatial.Topology; 
public partial class MainWindow : Window 
{ 
    private LocationCollection _polygonLocs = new LocationCollection(); 

    public MainWindow() 
    { 
     InitializeComponent(); 

     AddSquarePolygon(); 

     // angled line 1 
     LocationCollection slantedLocs = new LocationCollection(); 
     slantedLocs.Add(new Microsoft.Maps.MapControl.WPF.Location(40, -97)); 
     slantedLocs.Add(new Microsoft.Maps.MapControl.WPF.Location(35, -86)); 
     AddAndIntersectLine(slantedLocs); 

     // straight EW line 
     LocationCollection ewLocs = new LocationCollection(); 
     ewLocs.Add(new Microsoft.Maps.MapControl.WPF.Location(37, -97)); 
     ewLocs.Add(new Microsoft.Maps.MapControl.WPF.Location(37, -86)); 
     AddAndIntersectLine(ewLocs); 
    } 

    private void AddAndIntersectLine(LocationCollection lineLocs) 
    { 
     MapPolyline line = new MapPolyline() { Locations = lineLocs, Stroke = new SolidColorBrush(Colors.Black) }; 

     this._bingMap.Children.Add(line); 

     LocationCollection inters = Intersect(lineLocs, _polygonLocs); 

     MapPolyline interLine = new MapPolyline() { Locations = inters, Stroke = new SolidColorBrush(Colors.Red) }; 
     this._bingMap.Children.Add(interLine); 

    } 

    private void AddSquarePolygon() 
    { 
     _polygonLocs.Add(new Microsoft.Maps.MapControl.WPF.Location(39.0, -92)); 
     _polygonLocs.Add(new Microsoft.Maps.MapControl.WPF.Location(36.0, -92)); 
     _polygonLocs.Add(new Microsoft.Maps.MapControl.WPF.Location(36.0, -93)); 
     _polygonLocs.Add(new Microsoft.Maps.MapControl.WPF.Location(39.0, -93)); 

     MapPolygon square = new MapPolygon() 
     { 
      Locations = _polygonLocs, 
      Stroke = new SolidColorBrush(Colors.Black) 
     }; 

     this._bingMap.Children.Add(square); 
    } 

    public static LocationCollection Intersect(LocationCollection line, LocationCollection bounds) 
    { 
     Feature lineFeature = CreateFeatureFromLocations(line); 
     Feature boundsFeature = CreateFeatureFromLocations(bounds); 

     IFeature featureIntersection = boundsFeature.Intersection(lineFeature); 

     if (featureIntersection != null) 
     { 
      return (CreateLocationsFromFeature(featureIntersection)); 
     } 

     return new LocationCollection(); 
    } 


    private static LocationCollection CreateLocationsFromFeature(IFeature feature) 
    { 
     LocationCollection lc = new LocationCollection(); 
     foreach (var coords in feature.Coordinates) 
     { 
      lc.Add(new Microsoft.Maps.MapControl.WPF.Location(coords.Y, coords.X)); 
     } 

     return lc; 
    } 

    private static Feature CreateFeatureFromLocations(LocationCollection locs) 
    { 

     Coordinate[] coords = new Coordinate[locs.Count]; 
     long inx = 0; 

     foreach (var l in locs) 
     { 
      Coordinate coord = new Coordinate(); 
      coord.X = l.Longitude; 
      coord.Y = l.Latitude; 
      coords[inx] = coord; 
      inx++; 
     } 

     LineString ls = new LineString(coords); 
     MultiLineString mls = new MultiLineString(ls); 
     return new Feature(mls); 
    } 
} 

回答

1

這是因爲你的線是測地線(即:在大地水準線)。當繪製在平面地圖上時,它應該成爲一個圓弧,並且不再是直線。

1)你應該補充的是削減MapPolyline到若干段的功能,貼近現實

private static LocationCollection BuildGeodesicPolyline(Microsoft.Maps.MapControl.WPF.Location start, Microsoft.Maps.MapControl.WPF.Location end) 
    { 
     int segments = 32; // The number of line segments used to approximate the true curved route 
     LocationCollection latLongs = new LocationCollection(); 

     // Convert all coordinates to Radians 
     double lat1 = start.Latitude * (Math.PI/180); 
     double lon1 = start.Longitude * (Math.PI/180); 
     double lat2 = end.Latitude * (Math.PI/180); 
     double lon2 = end.Longitude * (Math.PI/180); 
     // Calculate the total extent of the route 
     double d = 2 * Math.Asin(Math.Sqrt(Math.Pow((Math.Sin((lat1 - lat2)/2)), 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Pow((Math.Sin((lon1 - lon2)/2)), 2))); 
     // Calculate the position at fixed intervals along the route 
     for (double n = 0; n < segments + 1; n++) 
     { 
      double f = (1d/segments) * n; 
      double A = Math.Sin((1 - f) * d)/Math.Sin(d); 
      double B = Math.Sin(f * d)/Math.Sin(d); 
      // Calculate 3D Cartesian coordinates of the point 
      double x = A * Math.Cos(lat1) * Math.Cos(lon1) + B * Math.Cos(lat2) * Math.Cos(lon2); 
      double y = A * Math.Cos(lat1) * Math.Sin(lon1) + B * Math.Cos(lat2) * Math.Sin(lon2); 
      double z = A * Math.Sin(lat1) + B * Math.Sin(lat2); 
      // Convert these to latitude/longitude 
      double lat = Math.Atan2(z, Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2))); 
      double lon = Math.Atan2(y, x); 
      // Create a VELatLong representing this location (remember to convert back to degrees) 
      double newLat = lat/(Math.PI/180d); 
      double newLon = lon/(Math.PI/180d); 
      Microsoft.Maps.MapControl.WPF.Location p = new Microsoft.Maps.MapControl.WPF.Location(newLat, newLon); 
      // Add this to the array 
      latLongs.Add(p); 
     } 

     return latLongs; 
    } 

http://www.beginningspatial.com/plotting_geography_linestrings_google_maps_and_virtual_earth

兩者繪製弧形如果你「的斜線1」之後添加這些行阻止你會看到黑色虛線是實際上是一個弧形:

slantedLocs = BuildGeodesicPolyline(new Microsoft.Maps.MapControl.WPF.Location(35d, -86d),new Microsoft.Maps.MapControl.WPF.Location(40d, -97d)) ; 
MapPolyline m = new MapPolyline() { Locations = slantedLocs, Stroke = new SolidColorBrush(Colors.Black), StrokeThickness = 2d, StrokeDashArray = new DoubleCollection(new List<double>() { 5, 5 }) }; 
_bingMap.Children.Add(m); 

2)你應該閱讀有關DotSpatial因爲紅線(導致Ø f交叉點)正在使用扁平座標系,因此對於您的目的而言是錯誤的。以下是SQL Server對此所說的內容:

declare @p geography = geography::STPolyFromText('POLYGON((-92 39 , -93 39 , -93 36 ,-92 36 , -92 39))',4326) 
declare @l1 geography = geography::STLineFromText('LINESTRING(-97 40, -86 35)',4326) 

declare @pG geometry = geometry::STPolyFromText('POLYGON((-92 39 , -93 39 , -93 36 ,-92 36 , -92 39))',4326) 
declare @l1G geometry = geometry::STLineFromText('LINESTRING(-97 40, -86 35)',4326) 
select 
@p.STIntersection(@l1).ToString() as [GEODESIC] -- LINESTRING (-92.0000000179902 37.936656236067556, -93.000000053162651 38.376235391098518) 
    , @pG.STIntersection(@l1G).ToString() as [PLANAR] -- LINESTRING (-93 38.18181818181818, -92 37.727272727272727) 

平面和測地幾何之間的幾何操作在這樣的比例上是不同的。

0

您的位置集合/交點測試不適用於海拔高度

您正在經歷這種情況,因爲有時候您的多邊形旁邊的點(在球形地圖上)不一定在您的多邊形之外。我們正在嘗試在2D平面上測試3D點。

剛纔在同樣的問題上撞了我的頭幾天!我想出了一個視覺上吸引人的修補程序,很簡單。

轉換所有的多邊形經緯度/長到Point對象使用LocationToViewPortpoint功能在屏幕上,以及您是相交測試點,並使用X和Y值,而不是你的緯度/長。