xamGeographicMap从SQL服务器数据绘制形状

本文关键字:绘制 数据 服务器 SQL xamGeographicMap | 更新日期: 2023-09-27 18:10:48

使用inffragistics xamGeographicMap控件,尝试从SQL server几何数据中添加形状。

  • 数据有效;
  • 当查询SP_GEOMETRY(参见示例)时,点显示正确—因此GeographicSymbolSeries工作,并且形状列包含实际数据
  • GeographicShapeSeries不工作
  • GeographicPolyLine不工作

        var majorCitySeries = new GeographicSymbolSeries
                              {
                                  ItemsSource = data.cities,
                                  LatitudeMemberPath = "SP_GEOMETRY.YCoordinate",
                                  LongitudeMemberPath = "SP_GEOMETRY.XCoordinate"
                              };
        GeoMap.Series.Add(majorCitySeries);

但是这些都没有显示:

       var countySeries = new GeographicShapeSeries
                           {
                               ItemsSource = data.counties,     
                               ShapeMemberPath = "SP_GEOMETRY"
                           };
        GeoMap.Series.Add(countySeries);
        var br = new GeographicPolylineSeries
                 {
                     ItemsSource = data.rivers,
                     ShapeMemberPath = "SP_GEOMETRY"
                 };
        GeoMap.Series.Add(br);

我需要添加一个转换器吗?样本,什么也说不出来。到底发生了什么事?

xamGeographicMap从SQL服务器数据绘制形状

好的,修复了。这是一个半通用的转换器:

public static class SqlGeometryToShapeConverter
{
    public static ShapefileConverter Create<T>(IEnumerable<T> items, 
                                               Func<T, DbGeometry> geoFunc, 
                                               Func<T, string> nameFunc) 
        where T : class
    {
        var converter = new ShapefileConverter();
        foreach (var item in items)
        {
            var rec = new ShapefileRecord();
            var points = new List<Point>();
            var geometry = geoFunc(item);
            Debug.Assert(geometry.PointCount != null, "geometry.PointCount != null");
            // Points are 1 based in DbGeometry
            var pointCount = geometry.PointCount;
            for (var pointIndex = 1; pointIndex <= pointCount; pointIndex++)
            {
                var point = geometry.PointAt(pointIndex);
                Debug.Assert(point.XCoordinate != null, "point.XCoordinate != null");
                Debug.Assert(point.YCoordinate != null, "point.YCoordinate != null");
                points.Add(new Point(point.XCoordinate.Value, point.YCoordinate.Value));
            }
            rec.Fields = new ShapefileRecordFields { { "Name", nameFunc(item) } };
            rec.Points = new List<List<Point>> { points };
            converter.Add(rec);
        }
        return converter;
    }
}

像这样使用:

        var countySeries = new GeographicShapeSeries
                           {
                               ItemsSource = SqlGeometryToShapeConverter.Create(data.counties, x => x.SP_GEOMETRY, x => x.County_Name),     
                               ShapeMemberPath = "Points"
                           };
        GeoMap.Series.Add(countySeries);

这对我来说是一个好的开始,但是我遇到了一些问题。这是我的方法,也许不那么优雅。与默认的inffragistics背景相比,这个地图有点偏离。我在SQL server中加载数据时可能有问题。

    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Data.SqlClient;
    using System.Windows;
    using Infragistics.Controls.Maps;
    using Microsoft.SqlServer.Types;
    namespace TestMVVMLightProject.Model
    {
        public class SqlGeometryToShapeConverter : ObservableCollection<ShapefileRecord>
        {
            public SqlGeometryToShapeConverter()
            {
                //connect
                //load sql
                //go thorugh points
                SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
                builder.DataSource = "localhost";
                builder.InitialCatalog = "RefDB_91_DistToCoast";
                builder.IntegratedSecurity = true;
                SqlConnection conn = new SqlConnection(builder.ConnectionString);
                conn.Open();
                string sql = "SELECT huc_2, geom FROM Polygon2";
                using (SqlCommand oCmd = new SqlCommand(sql, conn))
                {
                    oCmd.CommandTimeout = 3000;
                    using (SqlDataReader oDr = oCmd.ExecuteReader())
                    {
                        int ordGeom = oDr.GetOrdinal("geom");
                        int ordHucZone = oDr.GetOrdinal("huc_2");
                        double minX = double.MaxValue;
                        double minY = double.MaxValue;
                        double maxX = double.MinValue;
                        double maxY = double.MinValue;
                        while (oDr.Read())
                        {
                            var rec = new ShapefileRecord();
                            rec.Points = new List<List<Point>>();
                            SqlGeography coast = (SqlGeography)oDr.GetValue(ordGeom);
                            int numPolygons = (int)coast.STNumGeometries();
                            string hucZone = oDr.GetString(ordHucZone);
                            int hucInt = int.Parse(hucZone);
                            for (int geomIndex = 1; geomIndex <= coast.STNumGeometries(); geomIndex++)
                            {
                                SqlGeography polygon = coast.STGeometryN(geomIndex);
                                var points = new List<Point>();
                                for (int verticeIndex = 1; verticeIndex <= polygon.STNumPoints(); verticeIndex++)
                                {
                                    points.Add(new Point(polygon.STPointN(verticeIndex).Long.Value, polygon.STPointN(verticeIndex).Lat.Value));
                                    if (hucInt < 19)
                                    {
                                        minX = minX < polygon.STPointN(verticeIndex).Long.Value ? minX : polygon.STPointN(verticeIndex).Long.Value;
                                        minY = minY < polygon.STPointN(verticeIndex).Lat.Value ? minY : polygon.STPointN(verticeIndex).Lat.Value;
                                        maxX = maxX > polygon.STPointN(verticeIndex).Long.Value ? maxX : polygon.STPointN(verticeIndex).Long.Value;
                                        maxY = maxY > polygon.STPointN(verticeIndex).Lat.Value ? maxY : polygon.STPointN(verticeIndex).Lat.Value;
                                    }
                                }
                                rec.Points.Add(points);
                            }
                            rec.Fields = new ShapefileRecordFields { { "HUC_2", hucZone.ToString() } };
                            this.Add(rec);
                        }
                        worldRect = new Rect(new Point(minX, minY), new Point(maxX, maxY));
                    }
                }
                conn.Close();
            }
            private Rect worldRect; 
            public Rect WorldRect
            {
                get
                {
                    return worldRect;        
                }
            }
        }
    }

我从我的视图模型中调用这个(我使用MVVM Light)。这是我的视图模型中的代码。

    public MainViewModel()
    {
        mapData = new SqlGeometryToShapeConverter();
    }
    private SqlGeometryToShapeConverter mapData;
    public SqlGeometryToShapeConverter MapData
    {
        get
        {
            return mapData;
        }
        set
        {
            Set(() => MapData, ref mapData, value);
        }
    }

这是我的视图的一个片段

    <ig:XamGeographicMap Zoomable="True"
                             Height="400"
                             WorldRect="{Binding MapData.WorldRect}">
            <ig:XamGeographicMap.Series>
                <ig:GeographicShapeSeries ItemsSource="{Binding MapData}"
                                          ShapeMemberPath="Points"
                                          ShapeStyleSelector="{StaticResource shapeStyleSelector}"
                                          MarkerCollisionAvoidance="Fade">
                    <!-- custom marker with bindings to data loaded from database file (DBF) -->
                    <ig:GeographicShapeSeries.MarkerTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding Path=Item.Fields[HUC_2]}"
                                           Foreground="#FF333333"
                                           FontWeight="Bold"
                                           Margin="1 1 0 0" />
                            </Grid>
                        </DataTemplate>
                    </ig:GeographicShapeSeries.MarkerTemplate>
                </ig:GeographicShapeSeries>
            </ig:XamGeographicMap.Series>
        </ig:XamGeographicMap>