#c# #sql-server #infragistics #spatial-query
#c# #sql-сервер #инфраструктура #пространственный запрос
Вопрос:
Используя элемент управления Infragistics xamGeographicMap, пытаюсь добавить фигуры из данных геометрии SQL server.
- Данные верны; выбор в SSMS показывает фигуры правильно
- Точки отображаются правильно при запросе 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);
Нужно ли мне добавлять конвертер? Образцы, они ничего не говорят. Что дает?
Ответ №1:
Хорошо, исправлено. Вот полу-универсальный конвертер:
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);
Ответ №2:
Это было хорошее начало для меня, но я столкнулся с некоторыми проблемами. Вот мой, возможно, менее элегантный подход. По сравнению с фоном инфраструктуры по умолчанию, карта немного смещена. Возможно, что-то не так с моей загрузкой данных в 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>