TECH PLAY

GIS

イベント

該当するコンテンツが見つかりませんでした

マガジン

該当するコンテンツが見つかりませんでした

技術ブログ

aptpod Advent Calendar 2025 12月8日の記事です。 こんにちは、デザインチームの上野です。 はじめに QGISをつかってGEO TIFFファイルを書き出す QGISとは QGISのインストール 地図の領域を設定しGEO TIFFファイルを書き出す XYZタイルを用意し、レイヤーに追加する 測地系を変更する 書き出ししたい領域を矩形レイヤとして定義する GEO TIFF画像を書き出す [おまけ]領域の緯度経度を抽出する BlenderでGEO TIFFを読み込んで3Dマップ加工する Blenderとは Blenderのインストール Blender GISをつかう プラグインをインストールする 画像のインポート 建物の追加 モデルの調整 道路のトレースとモデルの追加 マテリアルの変更 完成 まとめ はじめに 近年、自動運転、都市計画、拡張現実(AR)、ゲーム開発といった様々な分野で デジタルツイン の需要が高まっています。 2Dマップや平面図では表現しきれなかった奥行きや構造物などを立体的に見ることができる 3Dマップ はこれらの先端技術を実用化するための鍵となっています。 しかし、本格的な3Dマップを作るとなれば制作の工程は複雑になりコストも高価になりがちです。 そこで本記事では、地理空間データの処理・分析に特化した無償のオープンソースGISソフトウェア 「QGIS」 と、無料の3Dモデリングツール 「Blender」 を連携させ、効率的かつ低コストで3D地図を作成する手法を紹介します。 以下の画像はQGISとBlenderをつかって作ったオフィス周辺のエリアの3Dマップ画像です。 本記事の手順を実施すると、下図のような3Dマップが作成できます。 作成した3Dマップは地形や建物の立体モデルとしてAR/ゲーム/都市計画/ロボティクス/自動運転の背景などに活用できます。 例えば走行中の車両のGPSデータと連携することで空間を視覚的に捉えることができるなど2Dのみではできなかった体験が可能となります。 作り方ですが QGISをつかってGEO TIFFファイルを書き出す BlenderでGEO TIFFを読み込んで3Dマップ加工する と、とてもシンプルな手法で作成しています。 QGISをつかってGEO TIFFファイルを書き出す QGISとは QGISは無料で使えるオープンソースのデスクトップ型地理情報システムソフトウェアで、地図データの表示、作成、編集、そして分析などが行えるアプリケーションです。 qgis.org QGISのインストール まずはQGISをインストールします。 QGISの公式サイト( https://www.qgis.org/download/ )にアクセスします。 寄付をしない場合は「Skip it and go to download」ボタンをクリックします。 ダウンロードページで、「長期リリース版(LTR)」の「QGIS Standalone Installer (64 bit)」などのインストーラーをクリックしてダウンロードを開始します。 ダウンロード後、インストーラーにしたがってインストールを行います。 地図の領域を設定しGEO TIFFファイルを書き出す インストールが完了したらQGISを起動させます。 ここでQGISで書き出したGEO TIFFは、後述するBlender側で「地形を生成する元データ」として使用します。 XYZタイルを用意し、レイヤーに追加する XYZタイルは、Web地図を高速に表示するために、地図画像を一定の大きさのタイルに分割し、それをサーバーが提供する仕組みです。 QGISでは、「XYZ Tiles」接続を利用することで、インターネット経由で配信されているタイル地図を簡単にプロジェクトに追加し、背景地図として活用できます。 まず、XYZタイルを右クリックし、接続を追加します。 ここではGoogle Mapの衛星写真を使用したいと思います。 名称を入力後、URLに https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z} と入力し[OK]を押します。 他のタイル情報に接続したい場合は XYZ Tiles(地図タイル)のURL一覧 を参考にしてください。 追加した接続をレイヤーにドラッグすれば地図が表示されます。 測地系を変更する 地図やGISで測地系が異なると、同じ緯度・経度を指していても、地球上の実際の位置が数メートルから数百メートルずれて表示されてしまいます。 そのため、異なるデータソースを重ね合わせて使う際は、必ず同じ測地系に統一する必要があります。 まずはプロジェクトで使用される座標系の変更を行います。 画面右下の [EPSG:〜]と書かれている箇所をクリックします。 設定画面がでたら測地系を選択します。 日本では平面直角座標系が全国で使用されています。 各都道府県で割り当てられている系統がことなるので こちら を参考に変更してください。 今回作るモデルは東京エリアにあるので該当する JGD2000 Japan Plane Rectangle CS IX を指定し、OKを押します。 座標系が変更されました。 書き出ししたい領域を矩形レイヤとして定義する 座標系が変更できたら書き出したい領域を設定していきます。 左上にある[新規シェープファイルレイヤ]をクリックし、以下の画像のように編集してレイヤを追加します。 レイヤ追加後は編集できるようになります。 [編集モード切り替え]を行えばいつでも地物の追加や削除など再編集することができます。 地図上の2箇所をクリックすることで矩形が生成されます。 またレイヤのスタイルは細かく設定することができます。 GEO TIFF画像を書き出す 書き出したい矩形を作成できたらGEO TIFFとして書き出します。 [OK]を押したら自動的に設定されたディレクトリにGEO TIFF画像が書き出されます。 次はBlenderの作業に入ります。 [おまけ]領域の緯度経度を抽出する QGISを使うメリットの一つとして、座標データを取得できることが挙げられます。 先ほど作成した矩形の四隅の平面直角座標を取得してみます。 矩形レイヤを選択し[ベクタ]→[ジオメトリツール]→[頂点を抽出]を選択します。 入力レイヤが合っているか確認し[実行]を押します。 そうすると矩形の四隅が抽出された 出力レイヤ が追加されます。 出力レイヤを選択した状態で[フィールド計算機]を押します。 属性テーブルに追加するフィールド名や計算式を以下のように設定します。 フィールドの名前を入力(任意の文字列) フィールド型を[小数点付き数値]にし、フィールド長の小数点以下の桁数を調整 式に $x と入力 (Y座標の場合は $y ) X座標とY座標でそれぞれ行います。 出力レイヤを右クリックし、メニューから[属性テーブル]を押します。 別ウィンドウが立ち上がり、先ほど計算したX座標、Y座標がテーブルで表示されます。 このとき、出力レイヤのスタイルでラベルをつけておくとどこの座標がどの位置にあるか視覚的にわかりやすくなります。 取得した値は平面直角座標系をベースにしたものでメートル単位の値になっています。 国土地理院のツール などを使用し変換することで緯度経度の値を取得することができます。 今回は外部ツールを使いましたが、もしかしたらQGIS内で変換できるかもしれません。 今後まだまだ機能含めてQGIS周りを調査していきたいと思います。 以上のようにして領域の矩形の四隅の緯度経度を抽出することができました。 BlenderでGEO TIFFを読み込んで3Dマップ加工する ちょっとしたおまけを挟みましたが、改めてBlenderでの作業にはいります。 Blenderとは Blenderは、オープンソースで無料の統合型3Dコンテンツ制作ソフトウェアです。 幅広い機能により、Blenderは映画制作、ゲーム開発、建築ビジュアライゼーション、プロダクトデザイン、3Dマップの作成など、様々な分野で世界的に利用されています。 www.blender.jp Blenderのインストール Blenderをインストールします。 Blenderの公式サイト( https://www.blender.org/ )にアクセスします。 トップページにある「Download Blender」ボタンをクリックします。ダウンロードページで、ご自身のOS(Windows、macOS、Linux)に対応した最新版の「Blender x.xx」のボタンをクリックし、インストーラーをダウンロードします。 ダウンロード後インストーラー起動し、インストールを完了します。 Blenderをインストールできたら起動し、 Blender GIS というアドオンを使用して画像をインポートします。 Blender GISをつかう プラグインをインストールする まずはBlender GISを使うためにプラグインをローカルにダウンロードします。 Blender GIS を開き、Clone or DownloadからDownload ZIPを選びダウンロードしてください。 BlenderでBelnder GISが使えるようにインポートします。 [編集]→[プリファレンス]を開きます。 [アドオン]を開き、右上のメニューから[ディスクからインストール]を選び、先ほどダウンロードしたZIPファイルを直接指定します。 追加されたあとチェックボックスにチェックを入れることでBlender GISが使用できるようになります。 BlenderのUIにGISのメニューが追加されます。 画像のインポート プラグインが使えるようになったらQGISから書き出したGEO TIFFをインポートします。 [GIS]→[インポート]→[Georeferenced raster(.tif .jpeg .jp2 .png)]をクリックし、書き出したGEO TIFF画像を読み込みます。 画像がインポートされ地図のモデルが生成されました。 建物の追加 Blender GISにはOSMを取得して該当エリア内のオブジェクトを生成する機能があります。 その機能を使って今回は建物を追加します。 [GIS]→[Web geodata]→[Get OSM]をクリックします。 どのOSMを取得するのかON/OFFできるので[Bulidng]をONにします。 建物のメッシュが生成されました。 モデルの調整 あとは3Dマップを使用するケースに合わせてモデリングを調整していきます。 道路のトレースとモデルの追加 例えばGPSで道路を走行するケースの場合、道路を強調したいといった目的がでてくるかと思います。 Blender GISのOSMで生成される道路は以下の画像のように生成されます。 これだと車線や道路の幅といった道路の正確性の表現がわかりにくいので、Adobe Illustratorを使って衛星写真からトレースしSVG形式で書き出します。 BlenderでSVG画像を読み込みスケールや位置などを調整するとこのようになります。 今回は大雑把にトレースしましたが白線なども同様に追加することでより詳細度を高めることができます。 マテリアルの変更 あとはお好みに合わせて各オブジェクトのマテリアルを調整します。 完成 まとめ いかがでしたでしょうか? 3Dマップを作るにあたって、最初はどうやって領域の緯度経度など値の正確性をだすのか、建物などのメッシュを一つ一つ作らないといけないのか、などとても難しいものだと考えていましたが、QGISとBlenderを使うことで十分なクオリティでデータの正確性も担保でき、かなりコストを抑えて作成できることがわかりました。 どちらも無料のソフトウェアで、使っているユーザーも多く、ネット上に有識者によるドキュメントもたくさんあるので是非調べながら手元で色々と試してみてはいかがでしょうか。
はじめに こんにちは、クラウドエース 第三開発部の松本です。 普段はデータ基盤や機械学習システムを構築したり、Google Cloud 認定トレーナーとしてトレーニングを提供しています。 今回は、Professional Data Engineer 試験対策ガイドのデータストレージ編として、データ取り込み編に続き、データストレージのプロダクトを中心に試験対策の内容をご紹介します! 尚、前回のデータ取り込み編をまだ見ていない方は、以下をぜひご覧ください。 https://zenn.dev/cloud_ace/articles/professional-data-engineer-dat
XI本部スマート ソサエティ センターの野網です。データ連携基盤に関連する 自治 体案件に携わっています。この 自治 体案件ではデータ連携基盤だけでなく、基盤上で提供するサービスについても検討しています。防災やインフラ管理の観点では、地図上でさまざまなデータを重ね合わせて可視化する GIS (地理情報システム)の実現が重要視されています。 Leaflet 今回は地図機能を提供する オープンソース の JavaScript ライブラリである「 Leaflet 」を触って色々と機能を確認してみました。 ベースとなる地図を指定できるか 地図上にピンを立てることができるか( Google Maps とかでよく見るもの) 地図上に任意の点/線/面を表示できるか 地図上に シェープファイル を表示できるか ベースマップ&ピンの表示 ベースマップとして、 OpenStreetMap 1 と 地理院 地図 2 を使用しました。また、駅の位置にピンを表示するレイヤーを作成しました。 Control.Layers を利用することで、ベースマップの切り替えやレイヤーの表示/非表示を実現しています。 // ベースマップ let osm = L . tileLayer ( 'https://tile.openstreetmap.org/{z}/{x}/{y}.png' , { maxZoom : 19 , attribution : '© OpenStreetMap' }) ; let gsi = L . tileLayer ( 'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png' , { attribution : '© 地理院地図' }) ; // ピン let shinagawa = L . marker ([ 35 . 6291112 , 139 . 7389313 ]) . bindPopup ( '品川駅' ) ; let takanawa_gateway = L . marker ([ 35 . 6355406 , 139 . 7407245 ]) . bindPopup ( '高輪ゲートウェイ駅' ) ; let stations = L . layerGroup ([ shinagawa , takanawa_gateway ]) ; // 地図セットアップ map = L . map ( 'map' , { center : [ 35 . 62455060680114 , 139 . 7395781036654 ] , zoom : 16 , layers : [ osm , stations ] }) ; let baseMaps = { "OpenStreetMap" : osm , "地理院地図" : gsi } ; let overlayMaps = { "駅" : stations } ; let layerControl = L . control . layers ( baseMaps , overlayMaps ) . addTo ( map ) ; 点/線/面、 シェープファイル の表示 最も基本的な描画機能である点/線/面の表示も確認します。これらはGeoJSON形式のファイルを読み込む形としており、非同期処理になっています。このファイルは手打ちで作成しました。 また、 GIS でよく出てくる シェープファイル の表示も行いました。 シェープファイル は 国土数値情報で公開されている道路のデータ を取得しています。Leafletには様々な プラグイン があり、 シェープファイル の表示に対応するものもありましたが、 日本語に対応していないという記事 があったので、この記事で紹介されている mapshaper を利用して シェープファイル をGeoJSON形式に事前に変換するという方法をとりました。 これらを先ほどのControl.Layersに追加し、期待していた機能を試すことができました。 async function fetchGeoJson ( filename ) { let response = await fetch ( filename ) ; return await response . json () ; } async function add_layer () { let my_geo_json = await fetchGeoJson ( "my_geojson_data.json" ) ; // GeoJSONレイヤーを追加 let my_geo_json_layer = L . geoJSON ( my_geo_json , { onEachFeature : function ( feature , layer ) { if ( feature . properties && feature . properties . name ) { layer . bindPopup ( feature . properties . name ) ; } } , style : function ( feature ) { switch ( feature . geometry . type ) { case 'Point' : return { color : "#ff0000" } ; case 'LineString' : return { color : "#0000ff" } ; case 'Polygon' : return { color : "#00ff00" } ; } } , pointToLayer : function ( feature , latlng ) { return L . circleMarker ( latlng , { radius : 8 , fillColor : "#ff0000" , color : "#000" , weight : 1 , opacity : 1 , fillOpacity : 0 . 8 }) ; } }) . addTo ( map ) ; my_geo_json_layer_group = L . layerGroup ([ my_geo_json_layer ]) ; layerControl . addOverlay ( my_geo_json_layer_group , "点/線/面" ) // 道路を追加 let road_feature = await fetchGeoJson ( "N01-07L-2K-13_Road.json" ) ; let road_layer = L . geoJSON ( road_feature , { style : function ( feature ) { return { color : "#ff00ff" } ; } }) . addTo ( map ) ; road_layer_group = L . layerGroup ([ road_layer ]) ; layerControl . addOverlay ( road_layer_group , "道路" ) } add_layer () ; サンプルコード 参考に今回の機能確認で利用したコードの全容を記載します。 index.html: <!DOCTYPE html> < html > < head > < title > Leaflet Sample Map </ title > < meta charset = "utf-8" /> < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > <!-- Leaflet CSS --> < link rel = "stylesheet" href = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity= "sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin = "" /> <!-- Leaflet Plugin CSS --> < link rel = "stylesheet" href = "https://unpkg.com/leaflet-switch-basemap@1.0.6/src/L.switchBasemap.css" crossorigin = "" /> < style > #map { width : 100% ; height : 600px ; } </ style > </ head > < body > < h1 > Leaflet Sample Map </ h1 > < div id = "map" ></ div > <!-- Leaflet JavaScript --> < script src = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity= "sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin = "" ></ script > <!-- アプリケーションのJavaScript --> < script src = "app.js" ></ script > </ body > </ html > app.js: // ベースマップ let osm = L . tileLayer ( 'https://tile.openstreetmap.org/{z}/{x}/{y}.png' , { maxZoom : 19 , attribution : '© OpenStreetMap' }) ; let gsi = L . tileLayer ( 'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png' , { attribution : '© 地理院地図' }) ; // ピン let shinagawa = L . marker ([ 35 . 6291112 , 139 . 7389313 ]) . bindPopup ( '品川駅' ) ; let takanawa_gateway = L . marker ([ 35 . 6355406 , 139 . 7407245 ]) . bindPopup ( '高輪ゲートウェイ駅' ) ; let stations = L . layerGroup ([ shinagawa , takanawa_gateway ]) ; // 地図セットアップ map = L . map ( 'map' , { center : [ 35 . 62455060680114 , 139 . 7395781036654 ] , zoom : 16 , layers : [ osm , stations ] }) ; let baseMaps = { "OpenStreetMap" : osm , "地理院地図" : gsi } ; let overlayMaps = { "駅" : stations } ; let layerControl = L . control . layers ( baseMaps , overlayMaps ) . addTo ( map ) ; async function fetchGeoJson ( filename ) { let response = await fetch ( filename ) ; return await response . json () ; } async function add_layer () { let my_geo_json = await fetchGeoJson ( "my_geojson_data.json" ) ; // GeoJSONレイヤーを追加 let my_geo_json_layer = L . geoJSON ( my_geo_json , { onEachFeature : function ( feature , layer ) { if ( feature . properties && feature . properties . name ) { layer . bindPopup ( feature . properties . name ) ; } } , style : function ( feature ) { switch ( feature . geometry . type ) { case 'Point' : return { color : "#ff0000" } ; case 'LineString' : return { color : "#0000ff" } ; case 'Polygon' : return { color : "#00ff00" } ; } } , pointToLayer : function ( feature , latlng ) { return L . circleMarker ( latlng , { radius : 8 , fillColor : "#ff0000" , color : "#000" , weight : 1 , opacity : 1 , fillOpacity : 0 . 8 }) ; } }) . addTo ( map ) ; my_geo_json_layer_group = L . layerGroup ([ my_geo_json_layer ]) ; layerControl . addOverlay ( my_geo_json_layer_group , "点/線/面" ) // 道路を追加 let road_feature = await fetchGeoJson ( "N01-07L-2K-13_Road.json" ) ; let road_layer = L . geoJSON ( road_feature , { style : function ( feature ) { return { color : "#ff00ff" } ; } }) . addTo ( map ) ; road_layer_group = L . layerGroup ([ road_layer ]) ; layerControl . addOverlay ( road_layer_group , "道路" ) } add_layer () ; app.js で参照している N01-07L-2K-13_Road.json は国土数値情報から取得した道路データです。色々なデータで試してみてください。 my_geojson_data. json : [ { " type ": " Feature ", " geometry ": { " type ": " Point ", " coordinates ": [ 139.7395781036654 , 35.62455060680114 ] } , " properties ": { " name ": " Sample Point " } } , { " type ": " Feature ", " geometry ": { " type ": " LineString ", " coordinates ": [ [ 139.73944850383708 , 35.62501310494848 ] , [ 139.73909069834616 , 35.62487771334422 ] , [ 139.73946289831088 , 35.62424755434228 ] ] } , " properties ": { " name ": " Sample Line " } } , { " type ": " Feature ", " geometry ": { " type ": " Polygon ", " coordinates ": [ [ [ 139.74004599801373 , 35.62494392209728 ] , [ 139.73961416239794 , 35.62473352999296 ] , [ 139.7398032581179 , 35.62440431429395 ] , [ 139.7401841317666 , 35.62449152388262 ] ] ] } , " properties ": { " name ": " Sample Polygon " } } ] おわりに シェープファイル をGeoJSON形式に変換が必要となる部分など、詰まることもありましたが、Leafletのような、 オープンソース のツールを使うことで、手軽に GIS の可能性を試すことができるのは魅力的だと感じました。 プラグイン も含めて機能が多数あり、サンプルも充実しているので、地図サービスに興味があればチェックしていただく価値があると思います。 私たちは一緒に働いてくれる仲間を募集しています! 社会課題解決ソリューションプロジェクト_システム開発プロジェクトマネージャー/リーダー 社会課題解決ソリューションプロジェクト_アーキテクト/テックリード クラウドアーキテクト 執筆: @noami.shunsuke 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました ) OpenStreetMap ↩ 国土地理院 ↩

動画

該当するコンテンツが見つかりませんでした

書籍