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);
我需要添加一个转换器吗?样本,什么也说不出来。到底发生了什么事?
好的,修复了。这是一个半通用的转换器:
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>