GeoJson ビューア(QML)

GeoJson ビューアのサンプルは、MapItems の操作方法、ユーザー入力の処理方法、GeoJson ファイルとの入出力方法を示しています。

この例では、様々な MapItems を持つマップを表示します。MapItems は、QtLocationGeoJsonData API を使って GeoJson ファイルからインポートされるか、TapHandlers を使ってユーザーによって描画される。

GeoJson ファイルの例は、example ディレクトリ内の data ディレクトリにある。

MapItem を描画するには、マップの何もない部分で右クリックし、表示されるメニューか ら好きなアイテムタイプを選択します。次のクリックで選択したアイテムが定義されます。この例では、MapCirclesMapRectanglesMapPolygonsMapPolylines を描画することができます。2つの点で完全に定義されるアイテム、すなわち円や長方形は、マウスの左ボタンを2回クリックすることで描画されます。複数の点で定義されるアイテム、つまり多角形や多角形は、任意の量の左ボタンクリックで作成され、右ボタンで完了します。この方法で描かれたアイテムは、GeoJson 仕様に合うように、ポイント、ポリゴン、ポリラインとして保存されます。https://geojson.org/ を参照してください。

例の実行

Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。

MapView の作成

まず、すべてのアイテムを配置できるベースマップを作成します。基本的なMap と入力処理(マウスホイール、ドラッグなど)を組み合わせたMapView 要素を利用します。基礎となるMap は、map プロパティでアクセスできます。MapView のプロパティを見逃した場合は、MapView.map でアクセスできる可能性が高い。

MapView {
    id: view
    anchors.fill: parent
    map.plugin: Plugin { name: "osm" }
    map.zoomLevel: 4
    map.center: QtPositioning.coordinate(3, 8)
}

GeoJson モデルのセットアップ / MapItems の表示

ファイルの内容を地図上に表示するために、モデル/ビュープログラミングとして知られるデザインパターンを使用します。まず、適切なビュー、この例ではMapItemView 要素をセットアップする必要があります。その親は、MapView 、その中に配置されたすべてのアイテムを正しく表示するために、その下にあるマップに設定する必要があります。

MapItemView {
    id: miv
    parent: view.map
}

次に、GeoJSONドキュメントを表す適切なモデルが必要です。この目的のために、QtLocation は GeoJSON ファイルを読み書きできるGeoJsonData 要素を提供しています。これは簡単にインスタンス化でき

GeoJsonData {
    id: geoDatabase
    sourceUrl: ":/data/11-full.json"
}

MapItemViewに割り当てることができる。

model: geoDatabase.model

例として、11-full.json ファイルが起動時に読み込まれる。

最後に、モデルデータをアイテムの表現に変換し、MapItemView を埋めるdelegate が必要です。

delegate: GeoJsonDelegate {}

GeoJsonDelegate 要素は、ファイルGeoJsonDelegate.qml で宣言されます。これはDelegateChooser 要素であり、異なるジオメトリ・タイプのさまざまな特性を考慮に入れています。

DelegateChooser {
    id: dc
    role: "type"
}

DelegateChooser には、GeoJson ファイルにあるジオメトリ タイプごとにDelegateChoice が含まれています。プロパティroleDelegateChoice.roleValue と照合され、正しいデリゲートが決定されます。

例として、GeoJson の"type":"Point" で記述された点は、MapItemView 上のMapCircle で表されます:

DelegateChoice {
    roleValue: "Point"
    delegate: MapCircle {
        property string geojsonType: "Point"
        property var props: modelData.properties
        geoShape: modelData.data
        radius: (props && props.radius) || 20*1000
        border.width: 2
        border.color: hh.hovered ? "magenta" : Qt.darker(color)
        opacity: dc.defaultOpacity
        color: (props && props.color) || (parent && parent.props && parent.props.color) || dc.defaultColor
    }
}

colorradius のようなMapCircle のプロパティは、modelData プロパティの形で利用可能な GeoJson ファイルから読み込もうとします。しかし、これは GeoJson の厳密な標準ではなく、すべてのプロパティにフォールバック値が設定される。

GeoJson への MapItems の書き込み

MapItems を GeoJson ファイルに書き込むには、GeoJsonData::saveAs 関数を指定のファイル名で呼び出すだけです。これにより、現在のモデル内の全アイテムが指定されたファイルに書き込まれる。ファイルに書き込むべき他のアイテムは、まず関数GeoJsonData::addItem またはGeoJsonData::setModelToMapContents を使ってモデルに追加する必要がある。

geoDatabase.saveAs(fileWriteDialog.selectedFile)

MapItems とのユーザーインタラクション

ユーザーとのインタラクションを扱うために、PointHandlers を使います。MouseArea とは対照的に、MapItem は常に正方形の形状をカバーするので、このタスクに特に適しています。GeoJson ファイルからインポートされた MapItems は、デリゲート内で直接HoverHandlerTapHandler を取得します:

TapHandler {
    onTapped: {
        if (props !== undefined)
            console.log(props.name)
        else if (parent.parent.geojsonType == "MultiPoint")
            console.log(parent.parent.props.name)
        else
            console.log("NO NAME!", props)
    }
}
HoverHandler {
    id: hh
}

TapHandler は、アイテムがタップされたときに、そのアイテムに関する情報をコンソールに書き込むた めに使用されます。HoverHandler は、マウスポインタの下にあるアイテムをハイライトするために使用されます。これは、HoverHandler のプロパティ / 状態hovered に応じてプロパティborder.color を記述することで実装されます。

新しいアイテムの追加

MapViewHoverHandlerTapHandler の組み合わせにより、ユーザーによるマウスの動きやクリックに反応することができます。

TapHandlersingleTapped シグナルを発すると、LeftButton で新しい MapItem を作成または修正し、RightButton で MapItem を終了する。終了する項目がない場合は、RightButton でメニューを開く。

onSingleTapped: (eventPoint, button) => {
    lastCoordinate = view.map.toCoordinate(tapHandler.point.position)
    if (button === Qt.RightButton) {
        if (view.unfinishedItem !== undefined) {
            view.finishGeoItem()
        } else
            mapPopupMenu.show(lastCoordinate)
    } else if (button === Qt.LeftButton) {
        if (view.unfinishedItem !== undefined) {
            if (view.unfinishedItem.addGeometry(view.map.toCoordinate(tapHandler.point.position), false)) {
                view.finishGeoItem()
            }
        }
    }
}

pointChanged シグナルは一時的に MapItem を更新し、ユーザーにプレビューを見せるために使われる。

HoverHandler {
    id: hoverHandler
    property variant currentCoordinate
    grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType

    onPointChanged: {
        currentCoordinate = view.map.toCoordinate(hoverHandler.point.position)
        if (view.unfinishedItem !== undefined)
            view.unfinishedItem.addGeometry(view.map.toCoordinate(hoverHandler.point.position), true)
    }
}

Mapitems は別々の qml ファイルで定義されたプロトタイプから生成される。それらはcreateComponent 関数を使って作成され、addMapItem でマップに追加される。新しいアイテムへの参照は、ユーザーがさらに操作できるように保存される。

function addGeoItem(item)
{
    var co = Qt.createComponent('mapitems/'+item+'.qml')
    if (co.status === Component.Ready) {
        unfinishedItem = co.createObject(map)
        unfinishedItem.setGeometry(tapHandler.lastCoordinate)
        unfinishedItem.addGeometry(hoverHandler.currentCoordinate, false)
        view.map.addMapItem(unfinishedItem)
    } else {
        console.log(item + " is not supported right now, please call us later.")
    }
}

アイテムを表示するには、Map にアイテムを追加するだけで十分です。しかし、そのアイテムをさらに使う(例えば、ファイルに保存する)ためには、モデルに追加する必要がある。これは編集が終わった後に行われます:

function finishGeoItem()
{
    unfinishedItem.finishAddGeometry()
    geoDatabase.addItem(unfinishedItem)
    map.removeMapItem(unfinishedItem)
    unfinishedItem = undefined
}

アイテムの削除

マップからすべてのアイテムを削除するには、GeoJsonData オブジェクトのリセット関数を呼び出すだけです。

function clearAllItems()
{
    geoDatabase.clear();
}

プロジェクトの例 @ code.qt.io

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。