Blazor 地理的データ モデルのバインディング
Ignite UI for Blazor マップ コンポーネントは、シェイプ ファイルからの地理空間データやデータ モデルからの地理的位置を地理的画像マップに表示するように設計されています。地理的シリーズの DataSource プロパティは、データ モデルへのバインディングのために使用されます。このプロパティは、カスタム オブジェクトの配列にバインドできます。
Blazor 地理的データ モデルのバインディングの例
以下の表で、地理的シリーズのタイプごとに必要となるデータ構造を簡単に説明します。
| Geographic シリーズ | プロパティ | 概要 |
|---|---|---|
IgbGeographicSymbolSeries |
LongitudeMemberPath、LatitudeMemberPath |
2 つの数値の経度と緯度座標の名前を指定します。 |
IgbGeographicHighDensityScatterSeries |
LongitudeMemberPath、LatitudeMemberPath |
2 つの数値の経度と緯度座標の名前を指定します。 |
IgbGeographicProportionalSymbolSeries |
LongitudeMemberPath、LatitudeMemberPath、RadiusMemberPath |
2 つの経度座標と緯度座標の名前と、シンボルのサイズ/半径の数字列を 1 列指定します。 |
IgbGeographicScatterAreaSeries |
LongitudeMemberPath、LatitudeMemberPath、ColorMemberPath |
数値の三角測量のために、2 つの経度と緯度座標および数値列を 1 列指定します。 |
IgbGeographicContourLineSeries |
LongitudeMemberPath、LatitudeMemberPath、ValueMemberPath |
数値の三角測量のために、2 つの経度と緯度座標および数値列を 1 列指定します。 |
IgbGeographicShapeSeries |
ShapeMemberPath |
図形の地理的ポイントを含む DataSource 項目のデータ列の名前を指定します。このプロパティは、x プロパティと y プロパティを持つオブジェクトの配列の配列にマップする必要があります。 |
IgbGeographicPolylineSeries |
ShapeMemberPath |
線の地理的座標を含む DataSource 項目のデータ列の名前を指定します。このプロパティは、x プロパティと y プロパティを持つオブジェクトの配列の配列にマップする必要があります。 |
コード スニペット
以下のコードは、IgbGeographicSymbolSeries を、経度と緯度の座標を使用して格納された世界の一部の都市の地理的位置を含むカスタム データ モデルにバインドする方法を示します。また、以下のコードで全体を示す MapGeodesics の大円距離の計算を使用してこれらの場所間の最短の地理的経路をプロットするために IgbGeographicPolylineSeries を使用します。
<IgbGeographicMap
@ref="geoMap"
Height="100%"
Width="100%"
Zoomable="true" />
@using IgniteUI.Blazor.Controls;
@using System;
@using System.Collections.Generic;
@using System.Linq;
// ...
public class GeoLocation
{
public double Lat { get; set; }
public double Lon { get; set; }
}
public class WorldCity
{
public double Lat { get; set; }
public double Lon { get; set; }
public double Pop { get; set; }
public string Country { get; set; }
public string Name { get; set; }
public bool Cap { get; set; }
}
public static class WorldUtils
{
public static List<List<Point>> CalcPaths(GeoLocation origin, GeoLocation dest)
{
int interval = 200;
var paths = new List<List<Point>>() { new List<Point>() };
int pathID = 0;
double distance = WorldUtils.CalcDistance(origin, dest);
if (distance <= interval)
{
paths[pathID].Add(new Point() { X = dest.Lon, Y = dest.Lat });
}
else
{
GeoLocation current = origin;
GeoLocation previous = origin;
for(int dist = interval; dist <= distance; dist += interval)
{
previous = current;
paths[pathID].Add(new Point() { X = current.Lon, Y = current.Lat });
double bearing = WorldUtils.CalcBearing(current, dest);
current = WorldUtils.CalcDestination(current, bearing, interval);
if (previous.Lon > 150 && current.Lon < -150)
{
paths[pathID].Add(new Point() { X = 180, Y = current.Lat });
paths.Add(new List<Point>());
pathID++;
current = new GeoLocation() { Lon = -180, Lat = current.Lat };
}
else if(previous.Lon < -150 && current.Lon > 150)
{
paths[pathID].Add(new Point() { X = -180, Y = current.Lat });
paths.Add(new List<Point>());
pathID++;
current = new GeoLocation() { Lon = 180, Lat = current.Lat };
}
}
paths[pathID].Add(new Point() { X = dest.Lon, Y = dest.Lat });
}
return paths;
}
public static double CalcBearing(GeoLocation origin, GeoLocation dest)
{
origin = WorldUtils.ToRadianLocation(origin);
dest = WorldUtils.ToRadianLocation(dest);
double range = (dest.Lon - origin.Lon);
double y = Math.Sin(range) * Math.Cos(dest.Lat);
double x = Math.Cos(origin.Lat) * Math.Sin(dest.Lat) - Math.Sin(origin.Lat) * Math.Cos(dest.Lat) * Math.Cos(range);
double angle = Math.Atan2(y, x);
return WorldUtils.ToDegreesNormalized(angle);
}
public static GeoLocation CalcDestination(GeoLocation origin, double bearing, double distance)
{
double radius = 6371.0;
origin = WorldUtils.ToRadianLocation(origin);
bearing = WorldUtils.ToRadians(bearing);
distance = distance / radius;
double lat = Math.Asin(Math.Sin(origin.Lat) * Math.Cos(distance) +
Math.Cos(origin.Lat) * Math.Sin(distance) * Math.Cos(bearing));
double x = Math.Sin(bearing) * Math.Sin(distance) * Math.Cos(origin.Lat);
double y = Math.Cos(distance) - Math.Sin(origin.Lat) * Math.Sin(origin.Lat);
double lon = origin.Lon + Math.Atan2(x, y);
// normalize lon to coordinate between -180º and +180º
lon = (lon + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
lon = WorldUtils.ToDegrees(lon);
lat = WorldUtils.ToDegrees(lat);
return new GeoLocation() { Lat = lat, Lon = lon };
}
public static double CalcDistance(GeoLocation origin, GeoLocation dest)
{
origin = WorldUtils.ToRadianLocation(origin);
dest = WorldUtils.ToRadianLocation(dest);
double sinProd = Math.Sin(origin.Lat) * Math.Sin(dest.Lat);
double cosProd = Math.Cos(origin.Lat) * Math.Cos(dest.Lat);
double lonDelta = (dest.Lon - origin.Lon);
double angle = Math.Acos(sinProd + cosProd * Math.Cos(lonDelta));
double distance = angle * 6371.0;
return distance;
}
public static GeoLocation ToRadianLocation(GeoLocation geoPoint)
{
double x = WorldUtils.ToRadians(geoPoint.Lon);
double y = WorldUtils.ToRadians(geoPoint.Lat);
return new GeoLocation() { Lon = x, Lat = y };
}
public static double ToRadians(double degrees)
{
return degrees * Math.PI / 180;
}
public static double ToDegrees(double radians)
{
return (radians * 180.0 / Math.PI);
}
public static double ToDegreesNormalized(double radians)
{
double degrees = WorldUtils.ToDegrees(radians);
degrees = (degrees + 360) % 360;
return degrees;
}
public static string ToStringLat(double latitude)
{
string str = Math.Abs(latitude) + "°";
return latitude > 0 ? str + "N" : str + "S";
}
public static string ToStringLon(double coordinate)
{
double val = Math.Abs(coordinate);
string str = val.ToString();
return coordinate > 0 ? str + "°E" : str + "°W";
}
public static string ToStringAbbr(double value)
{
if (value > 1000000000000)
{
return (value / 1000000000000).ToString("N1") + " T";
}
else if (value > 1000000000)
{
return (value / 1000000000).ToString("N1") + " B";
}
else if (value > 1000000)
{
return (value / 1000000).ToString("N1") + " M";
}
else if (value > 1000)
{
return (value / 1000).ToString("N1") + " K";
}
return value.ToString("N0");
}
public static double GetLongitude(GeoLocation location)
{
return location.Lon;
}
public static double GetLatitude(GeoLocation location)
{
return location.Lat;
}
public static Rect GetBounds(List<GeoLocation> locations)
{
double minLat = 90;
double maxLat = -90;
double minLon = 180;
double maxLon = -180;
foreach(GeoLocation gl in locations)
{
double curLon = WorldUtils.GetLongitude(gl);
double curLat = WorldUtils.GetLatitude(gl);
if (!double.IsNaN(curLon))
{
minLon = Math.Min(minLon, curLon);
maxLon = Math.Max(maxLon, curLon);
}
if (!double.IsNaN(curLat))
{
minLat = Math.Min(minLat, curLat);
maxLat = Math.Min(maxLat, curLat);
}
}
Rect geoBounds = new Rect(minLon, minLat, Math.Abs(maxLon - minLon), Math.Abs(maxLat - minLat));
return geoBounds;
}
public static List<Point> GetNightShapes()
{
List<Point> line = new List<Point>();
for(int lon = -180; lon <= 180; lon += 1)
{
double x = lon;
double y = 75 * Math.Cos(lon * Math.PI / 180);
line.Add(new Point(x, y));
}
return line;
}
}
public class FlightInfo
{
public WorldCity Origin { get; set; }
public WorldCity Dest { get; set; }
public double Distance { get; set; }
public double Time { get; set; }
public List<List<Point>> Points { get; set; }
public string Color { get; set; }
}
// ...
public void MapBindingDataModelOnViewInit()
{
var geoMap = this.geoMap;
geoMap.UpdateZoomWindow(new Rect() { Left = 0.2, Top = 0.1, Width = 0.6, Height = 0.6 });
var CityDAL = new WorldCity() { Lat = 32.763, Lon = -96.663, Country = "US", Name = "Dallas" };
var CitySYD = new WorldCity() { Lat = -33.889, Lon = 151.028, Country = "Australia", Name = "Sydney" };
var CityNZL = new WorldCity() { Lat = -36.848, Lon = 174.763, Country = "New Zealand", Name = "Auckland" };
var CityQTR = new WorldCity() { Lat = 25.285, Lon = 51.531, Country = "Qatar", Name = "Doha" };
var CityPAN = new WorldCity() { Lat = 8.949, Lon = -79.4, Country = "Panama", Name = "Panama" };
var CityCHL = new WorldCity() { Lat = -33.475, Lon = -70.647, Country = "Chile", Name = "Santiago" };
var CityJAP = new WorldCity() { Lat = 35.683, Lon = 139.809, Country = "Japan", Name = "Tokyo" };
var CityALT = new WorldCity() { Lat = 33.795, Lon = -84.349, Country = "US", Name = "Atlanta" };
var CityJOH = new WorldCity() { Lat = -26.178, Lon = 28.004, Country = "South Africa", Name = "Johannesburg" };
var CityNYC = new WorldCity() { Lat = 40.75, Lon = -74.0999, Country = "US", Name = "New York" };
var CitySNG = new WorldCity() { Lat = 1.229, Lon = 104.177, Country = "Singapore", Name = "Singapore" };
var CityMOS = new WorldCity() { Lat = 55.75, Lon = 37.7, Country = "Russia", Name = "Moscow" };
var CityROM = new WorldCity() { Lat = 41.88, Lon = 12.52, Country = "Italy", Name = "Roma" };
var CityLAX = new WorldCity() { Lat = 34.0, Lon = -118.25, Country = "US", Name = "Los Angeles" };
var flights = new List<FlightInfo>() {
new FlightInfo() { Origin = CityDAL, Dest = CitySNG, Color = "Green" },
new FlightInfo() { Origin = CityMOS, Dest = CityNZL, Color = "Red" },
new FlightInfo() { Origin = CityCHL, Dest = CityJAP, Color = "Blue" },
new FlightInfo() { Origin = CityPAN, Dest = CityROM, Color = "Orange" },
new FlightInfo() { Origin = CityALT, Dest = CityJOH, Color = "Black" },
new FlightInfo() { Origin = CityNYC, Dest = CityQTR, Color = "Purple" },
new FlightInfo() { Origin = CityLAX, Dest = CitySYD, Color = "Gray" }
};
// the route first, so that the cities at either end of it draw on top
foreach (var flight in flights)
{
AddFlightRoute(geoMap, flight);
AddFlightCities(geoMap, flight);
}
}
/// <summary>The flight itself, as a great circle path between its two cities.</summary>
public void AddFlightRoute(IgbGeographicMap geoMap, FlightInfo flight)
{
var geoOrigin = new GeoLocation() { Lat = flight.Origin.Lat, Lon = flight.Origin.Lon };
var geoDest = new GeoLocation() { Lat = flight.Dest.Lat, Lon = flight.Dest.Lon };
var geoDistance = WorldUtils.CalcDistance(geoOrigin, geoDest);
var geoRoutes = new List<FlightInfo>() {
new FlightInfo() {
Points = WorldUtils.CalcPaths(geoOrigin, geoDest),
Origin = flight.Origin,
Dest = flight.Dest,
Distance = geoDistance,
Time = geoDistance / 850
}
};
var lineSeries = new IgbGeographicPolylineSeries();
lineSeries.DataSource = geoRoutes;
lineSeries.ShapeMemberPath = "Points";
lineSeries.ShapeStrokeThickness = 9;
lineSeries.ShapeOpacity = 0.5;
lineSeries.ShapeStroke = flight.Color;
geoMap.Series.Add(lineSeries);
}
/// <summary>The cities at either end, in the flight's own colour.</summary>
public void AddFlightCities(IgbGeographicMap geoMap, FlightInfo flight)
{
var geoLocations = new List<WorldCity>() { flight.Origin, flight.Dest };
var symbolSeries = new IgbGeographicSymbolSeries();
symbolSeries.DataSource = geoLocations;
symbolSeries.MarkerType = MarkerType.Circle;
symbolSeries.LatitudeMemberPath = "Lat";
symbolSeries.LongitudeMemberPath = "Lon";
symbolSeries.MarkerBrush = "White";
symbolSeries.MarkerOutline = flight.Color;
symbolSeries.Thickness = 1;
geoMap.Series.Add(symbolSeries);
}
API リファレンス
IgbGeographicContourLineSeries
IgbGeographicHighDensityScatterSeries
IgbGeographicPolylineSeries
IgbGeographicProportionalSymbolSeries
IgbGeographicScatterAreaSeries
IgbGeographicSymbolSeries