Close
Angular React Web Components Blazor React
Premium

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

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

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

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

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

コード スニペット

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

<IgrGeographicMap
    ref={this.geoMapRef}
    height="100%"
    width="100%"
    zoomable={true} />
import { IgrGeographicPolylineSeries, IgrGeographicSymbolSeries } from 'igniteui-react-maps';
import { MarkerType } from 'igniteui-react-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 IgrGeographicPolylineSeries({ name: "geographicPolylineSeries1" });
    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 IgrGeographicSymbolSeries({ name: "geographicSymbolSeries1" });
    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 リファレンス

IgrGeographicContourLineSeries
IgrGeographicHighDensityScatterSeries
IgrGeographicPolylineSeries
IgrGeographicProportionalSymbolSeries
IgrGeographicScatterAreaSeries
IgrGeographicSymbolSeries