とりあえずここまでいった。寝よ。
12/3
できた。
MapBoxで
上のやつはできた勢いで書いただけなので、さらっと流れを書いておく。書く以外にも難儀していたけどそこまで覚えてないや。基本的な流れはこちらを参考にした。道路上とかはやってない。大変ありがたかったです。
日本の範囲内にマーカーを散らばす
参考サイトではturfのrandomを使っていたけど、java版には無いみたいなのでそこは手動でやる。そんでJSONObjectができたと。
JSONObject obj = new JSONObject(); obj = makeJSON(); FeatureCollection featureCollection = FeatureCollection.fromJson(obj.toString());
JSONObjectをtoStringでString型にして、FeatureCollection.fromJsonでMapboxで扱えるようになった。日本範囲内のPointのデータの集まりなので、そこには座標も含まれてる。その座標を元にマーカーを設置していけば、↑の1枚目の画像になる。
参考

そういえば↑見るとGoogleMapでもgeoJSON扱えそうなんだよな…。

これとか、どうなんだろ。
日本の陸地に含まれてるマーカーだけにする
参考サイトに日本のポリゴンがあったので、それを拝借した。それを同じようにMapboxで扱えるようにして、Turfのinsideメソッドで判定してあげれば、残るのは陸地内ということだ。
アプリローカルにファイルを設置
assetsフォルダを作る。
以前別の記事でraw作る時に上の方のAndroidResourceDirectryを使っていたけど、普通に下の方にそれそのものがあった。えへへ。ちなみになんでassetsなのかは知らない。そんで、その中に落としてきたjapan_outline.geojsonをペースト。
assetsから読み込んでJSONにする
ここがすごーく難儀した。いやちゃんと理解してないままやろうとした自分が全部悪いんだけどさ。
MultiPolygon mp; StringBuilder builder = new StringBuilder(); InputStream is;
FeatureCollection fc; AssetManager assetManager = getResources().getAssets(); try { is = assetManager.open("japan_outline.geojson"); } catch (IOException e) { e.printStackTrace(); } try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is)); String str; while ((str = bufferedReader.readLine()) != null) { builder.append(str); } JSONObject json = new JSONObject(builder.toString());
動いてくれたコードね。知らなかった言葉がたくさんある。AssetManager, InputStream, BufferedReader, StringBuilder,List<>ふんわり理解していこう。
AssetManager
assetsフォルダにあるファイルを使う時に使用するやつ。getResouce().getAssets()で使う準備。そんでassetManager.open(filename)でファイルを開く。
InputStream, InputStreamReader, BufferedReader
- InputStream
読み込んだファイルをふわっとした感じにしてくれる。
- InputStreamReader
ふわっとした感じをJavaで扱える感じにしてくれる。
- BufferedReader
Javaで扱える感じをゆったり読み込んでくれる。
StringBuilder
文字列を組み立てるんだろうなー。今回は、BufferedReaderで一行ずつ読み込んだやつを、1個にまとめてくれる。そういえば、元のファイルが複数行になっている場合
while ((str = bufferedReader.readLine()) != null) { builder.append(str); }
としないと、全部読み込んでくれない。俺ははこれをやってなくて、最初の行しか読み込まれずエラー出まくって、デバックしてやっと気づいた。
ほいでStringBuilderからtoStringして、JSONObjectにすると。
…これはもう定形として覚えるだけでいいかな…。
参考


turfJoins.insideで扱えるようにgeoJSON型にする
今読み込んでるのは、日本の陸地のポリゴンで、JSONObject型になってる。turfJoins.insideは
public static boolean inside(com.mapbox.geojson.Point point, com.mapbox.geojson.MultiPolygon multiPolygon)
と、引数をMultiPolygon型(もしくはPolygon型)にしないといけない。
fc = FeatureCollection.fromJson(json.toString()); List<Feature> featuresjp = fc.features(); Feature ft = featuresjp.get(0); mp = (MultiPolygon) ft.geometry(); } catch (JSONException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
先ほどと同じようにFeatureCollection型にする。FeatureCollectionは.fetures()でList<Feature>を返す。List<>っつーのは動的配列みたいなもんらしい。.get(index)で単体のFeatureが取得できる。indexは0始まりみたい、japan_outline.geojsonの構成を見ながらどこに何が配置されてるか理解しながらやんないとダメだった。ちなみにindexを1にしてエラー出したのが私だ。そんで.geometry()でFeatureの内部を取得できる。geometryはいくつか種類があるので、適切な形(ここではMultiPlygon)にキャストしてあげる。できた。
参考

日本の範囲内のPointデータと日本の範囲を表すデータを比較してマーカーを配置する
やっとturfが使える。
List<Feature> features = featureCollection.features(); mapView.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(@NonNull MapboxMap mapboxMap) { mapboxMapm = mapboxMap; for (Feature f : features) { Point p = (Point) f.geometry(); if (TurfJoins.inside(p, mp)) { marker = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(p.latitude(), p.longitude()))); marker.setIcon(icon01); } } } });
これ↓は
mapView.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(@NonNull MapboxMap mapboxMap) { … };
こう書こうねとサンプルがなってたのでこう書いた。
ランダムPointのデータをList<Feature>型にする。Listは拡張for文が使えるみたいなので、それぞれのFeatureをPoint型にキャストし、それが日本の範囲内にあるかどうかをturfjoins.insideで判定する。戻り値がtrueだったらmarkerをその位置に追加し、.setIcon()する。
これで上から2番目の画像になった、と。
コメント