Close
Angular React Web Components Blazor Web Components
Premium

Web Components 地理的データ モデルのバインディング

Ignite UI for Web Components マップ コンポーネントは、シェイプ ファイルからの地理空間データやデータ モデルからの地理的位置を地理的画像マップに表示するように設計されています。地理的シリーズの dataSource プロパティは、データ モデルへのバインディングのために使用されます。このプロパティは、カスタム オブジェクトの配列にバインドできます。

Web Components 地理的データ モデルのバインディングの例

以下の表で、地理的シリーズのタイプごとに必要となるデータ構造を簡単に説明します。

Geographic シリーズ プロパティ 概要
IgcGeographicSymbolSeriesComponent longitudeMemberPath、latitudeMemberPath 2 つの数値の経度と緯度座標の名前を指定します。
IgcGeographicHighDensityScatterSeriesComponent longitudeMemberPath、latitudeMemberPath 2 つの数値の経度と緯度座標の名前を指定します。
IgcGeographicProportionalSymbolSeriesComponent longitudeMemberPath、latitudeMemberPath、radiusMemberPath 2 つの経度座標と緯度座標の名前と、シンボルのサイズ/半径の数字列を 1 列指定します。
IgcGeographicScatterAreaSeriesComponent longitudeMemberPath、latitudeMemberPath、colorMemberPath 数値の三角測量のために、2 つの経度と緯度座標および数値列を 1 列指定します。
IgcGeographicContourLineSeriesComponent longitudeMemberPath、latitudeMemberPath、valueMemberPath 数値の三角測量のために、2 つの経度と緯度座標および数値列を 1 列指定します。
IgcGeographicShapeSeriesComponent shapeMemberPath 図形の地理的ポイントを含む dataSource 項目のデータ列の名前を指定します。このプロパティは、x プロパティと y プロパティを持つオブジェクトの配列の配列にマップする必要があります。
IgcGeographicPolylineSeriesComponent shapeMemberPath 線の地理的座標を含む dataSource 項目のデータ列の名前を指定します。このプロパティは、x プロパティと y プロパティを持つオブジェクトの配列の配列にマップする必要があります。

コード スニペット

以下のコードは、IgcGeographicSymbolSeriesComponent を、経度と緯度の座標を使用して格納された世界の一部の都市の地理的位置を含むカスタム データ モデルにバインドする方法を示します。また、以下のコードで全体を示す MapGeodesics の大円距離の計算を使用してこれらの場所間の最短の地理的経路をプロットするために IgcGeographicPolylineSeriesComponent を使用します。

<igc-geographic-map
    id="geoMap"
    height="100%"
    width="100%"
    zoomable="true">
</igc-geographic-map>
import { IgcGeographicPolylineSeriesComponent, IgcGeographicSymbolSeriesComponent } from 'igniteui-webcomponents-maps';
import { MarkerType } from 'igniteui-webcomponents-charts';
// ...
/**
 * Great circle maths for a map: the path between two locations, and how far apart they are.
 */
export class MapGeodesics {

    // calculate geo-paths between two locations using great circle formula
    public calcPaths(origin: any, dest: any): any[] {
        let interval = 200;
        let paths: any[] = [[]];
        let pathID = 0;
        let distance = this.calcDistance(origin, dest);
        if (distance <= interval) {
            paths[pathID].push({ x: origin.lon, y: origin.lat });
            paths[pathID].push({ x: dest.lon, y: dest.lat });
        } else {
            let current = origin;
            let previous = origin;

            for (let dist = interval; dist <= distance; dist += interval)
            {
                previous = current
                paths[pathID].push({ x: current.lon, y: current.lat });

                let bearing = this.calcBearing(current, dest);
                current = this.calcDestination(current, bearing, interval);
                // ensure geo-path wrap around the world through the new date-line
                if (previous.lon > 150 && current.lon < -150) {
                    paths[pathID].push({ x: 180, y: current.lat });
                    paths.push([]);
                    pathID++
                    current = { lon: -180, lat: current.lat }
                } else if (previous.lon < -150 && current.lon > 150) {
                    paths[pathID].push({ x: -180, y: current.lat });
                    paths.push([]);
                    pathID++
                    current = { lon: 180, lat: current.lat }
                }
            }
            paths[pathID].push({ x: dest.lon, y: dest.lat });
        }
        return paths;
    }

    // calculate bearing angle between two locations
    public calcBearing(origin: any, dest: any): number
    {
        origin = this.toRadianLocation(origin);
        dest = this.toRadianLocation(dest);
        let range = (dest.lon - origin.lon);
        let y = Math.sin(range) * Math.cos(dest.lat);
        let x = Math.cos(origin.lat) * Math.sin(dest.lat) -
                Math.sin(origin.lat) * Math.cos(dest.lat) * Math.cos(range);
        let angle = Math.atan2(y, x);
        return this.toDegreesNormalized(angle);
    }

    // calculate destination for origin location and travel distance
    public calcDestination(origin: any, bearing: number, distance: number): any {
        let radius = 6371.0;
        origin = this.toRadianLocation(origin);
        bearing = this.toRadians(bearing);
        distance = distance / radius; // angular distance in radians

        let lat = Math.asin(Math.sin(origin.lat) * Math.cos(distance) +
                       Math.cos(origin.lat) * Math.sin(distance) * Math.cos(bearing));
        let x = Math.sin(bearing) * Math.sin(distance) * Math.cos(origin.lat);
        let y = Math.cos(distance) - Math.sin(origin.lat) * Math.sin(origin.lat);
        let 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 = this.toDegrees(lon);
        lat = this.toDegrees(lat);

        return { lon: lon, lat: lat };
    }

    // calculate distance between two locations
    public calcDistance(origin: any, dest: any): number {
        origin = this.toRadianLocation(origin);
        dest = this.toRadianLocation(dest);
        let sinProd = Math.sin(origin.lat) * Math.sin(dest.lat);
        let cosProd = Math.cos(origin.lat) * Math.cos(dest.lat);
        let lonDelta = (dest.lon - origin.lon);

        let angle = Math.acos(sinProd + cosProd * Math.cos(lonDelta));
        let distance = angle * 6371.0;
        return distance; // * 6371.0; // in km
    }

    public toRadianLocation(geoPoint: any): any {
        let x = this.toRadians(geoPoint.lon);
        let y = this.toRadians(geoPoint.lat);
        return { lon: x, lat: y };
    }

    public toRadians(degrees: number): number
    {
        return degrees * Math.PI / 180;
    }

    public toDegrees(radians: number): number {
        return (radians * 180.0 / Math.PI);
    }

    public toDegreesNormalized(radians: number): number
    {
        let degrees = this.toDegrees(radians);
        degrees = (degrees + 360) % 360;
        return degrees;
    }
}
// ...
private mapGeodesics: MapGeodesics = new MapGeodesics();

public mapBindingDataModelOnViewInit(): void {
    var geoMap = this.geoMap;
    geoMap.updateZoomWindow({ left: 0.2, top: 0.1, width: 0.6, height: 0.6 });

    var cityDAL = { lat: 32.763, lon: -96.663, country: "US", name: "Dallas" };
    var citySYD = { lat: -33.889, lon: 151.028, country: "Australia", name: "Sydney" };
    var cityNZL = { lat: -36.848, lon: 174.763, country: "New Zealand", name: "Auckland" };
    var cityQTR = { lat: 25.285, lon: 51.531, country: "Qatar", name: "Doha" };
    var cityPAN = { lat: 8.949, lon: -79.4, country: "Panama", name: "Panama" };
    var cityCHL = { lat: -33.475, lon: -70.647, country: "Chile", name: "Santiago" };
    var cityJAP = { lat: 35.683, lon: 139.809, country: "Japan", name: "Tokyo" };
    var cityALT = { lat: 33.795, lon: -84.349, country: "US", name: "Atlanta" };
    var cityJOH = { lat: -26.178, lon: 28.004, country: "South Africa", name: "Johannesburg" };
    var cityNYC = { lat: 40.75, lon: -74.0999, country: "US", name: "New York" };
    var citySNG = { lat: 1.229, lon: 104.177, country: "Singapore", name: "Singapore" };
    var cityMOS = { lat: 55.75, lon: 37.7, country: "Russia", name: "Moscow" };
    var cityROM = { lat: 41.88, lon: 12.52, country: "Italy", name: "Roma" };
    var cityLAX = { lat: 34.0, lon: -118.25, country: "US", name: "Los Angeles" };

    var flights = [
        { origin: cityDAL, dest: citySNG, color: "Green" },
        { origin: cityMOS, dest: cityNZL, color: "Red" },
        { origin: cityCHL, dest: cityJAP, color: "Blue" },
        { origin: cityPAN, dest: cityROM, color: "Orange" },
        { origin: cityALT, dest: cityJOH, color: "Black" },
        { origin: cityNYC, dest: cityQTR, color: "Purple" },
        { origin: cityLAX, dest: citySYD, color: "Gray" }
    ];

    // the route first, so that the cities at either end of it draw on top
    for (var i = 0; i < flights.length; i++) {
        this.addFlightRoute(geoMap, flights[i]);
        this.addFlightCities(geoMap, flights[i]);
    }
}

/** the flight itself, as a great circle path between its two cities */
public addFlightRoute(geoMap: any, flight: any): void {
    var geodesics = this.mapGeodesics;
    var geoPath = geodesics.calcPaths(flight.origin, flight.dest);
    var geoDistance = geodesics.calcDistance(flight.origin, flight.dest);
    var geoRoutes = [{
        points: geoPath,
        origin: flight.origin,
        dest: flight.dest,
        distance: geoDistance,
        time: geoDistance / 850
    }];

    var lineSeries = new IgcGeographicPolylineSeriesComponent();
    lineSeries.dataSource = geoRoutes;
    lineSeries.shapeMemberPath = "points";
    lineSeries.shapeStrokeThickness = 9;
    lineSeries.shapeOpacity = 0.5;
    lineSeries.shapeStroke = flight.color;
    geoMap.series.add(lineSeries);
}

/** the cities at either end, in the flight's own colour */
public addFlightCities(geoMap: any, flight: any): void {
    var geoLocations = [flight.origin, flight.dest];

    var symbolSeries = new IgcGeographicSymbolSeriesComponent();
    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 リファレンス

IgcGeographicContourLineSeriesComponent
IgcGeographicHighDensityScatterSeriesComponent
IgcGeographicPolylineSeriesComponent
IgcGeographicProportionalSymbolSeriesComponent
IgcGeographicScatterAreaSeriesComponent
IgcGeographicSymbolSeriesComponent