地図アプリは約10年前の2015年2月か3月頃に開発を始めたものである。 当初は Windowsパソコン/タブレット用として C# で作成した。
3年前にAndroidスマホに移植した。プログラミング言語は最初は Microsoft Visual Studio の C# を考えたが、 グラフィックス関連のAPIは Windows とは全く互換性がないことが分かった。 Android OS の更新はWindows OSよりも非常に速いため、Microsoft Visual Studioの使用には不安があり、 C# をやめて、Android Javaを使うことにした。
現在は地図アプリはスマホでの使用がメインであるが、OSM(OpenStreetMap)のマッピング作業などでは、 パソコンでの地図アプリ利用が望ましい。
スマホとの互換性を考慮すると、開発言語は C#よりも本家Java(サンマイクロシステムズ -> Oracle)の方が望ましい。
少し調べた限りでは、C#のグラフィックスの方が充実しているため、プログラム開発の負担は増えるが、 PC版での地図アプリ経験をスマホ版地図アプリに活かせるため Java を使うことにした。
OSMのxmlデータをパソコンでバイナリレコードに変換するが、これは Java でないと負担がかかる。
最初にごく一部のプログラムだけを作成して動作確認を行った。道路や鉄道の描画はまだ正しいものではない。
国土地理院地図の場合、レンダリングはないので、きわめて簡単であり、特に問題はない。
OSM地図のレンダリングはまだ不完全なものである。道路はまだ描画していない。鉄道の描画も途中段階である。
15年ほど前には本家Javaも使ったが、その後の発展も大きいようである。
現在、座標値列データは int[] xpoints、int[] ypoints としている。
現在は次のようにしている。実際には、幅のある道路や破線描画では、さらにオプション引数が加わる。 引数 Renderer r はいらないかもしれない。
int[] xpoints、int[] ypoints は float[] xpoints、float[] ypoints に変える。 Line2D.Double は Line2D.Float に変更する。
void drawLine(Graphics2D g, Renderer r, Paint p, float width) { if (xpoints == null) return; g.setPaint(p); g.setStroke(new BasicStroke(width)); for (int i=1; i < xpoints.length; i++) { g.draw(new Line2D.Double(xpoints[i-1], ypoints[i-1], xpoints[i], ypoints[i])); } }
穴あきポリゴン(マルチポリゴン)への対応は Android Java より簡単である。 ただし、new Polygon(int[] x, int[] y, int len) であるから、 int[] xpoints、int[] ypoints を float[] xpoints、float[] ypoints に変更できない。 float x は (int)x により簡単に int に変換できるが、 float[] xpoints は (int[])xpoints ではすまない。
// マルチポリゴン対応 void fillPolygon(Graphics2D g, Renderer r, Paint paint, Color border) { if (type == 3) { Area area = new Area(); Polygon poly = new Polygon(xpoints, ypoints, xpoints.length); area.add(new Area(poly)); for (int n = 0; n < xpolys.length; n++) { poly = new Polygon(xpolys[n], ypolys[n], xpolys[n].length); area.subtract(new Area(poly)); } g.setPaint(paint); g.fill(area); if (border != null) { g.setStroke(new BasicStroke(0.3f)); g.setPaint(border); g.draw(area); } } else if (type == 2) { Polygon polygon = new Polygon(xpoints, ypoints, xpoints.length); g.setPaint(paint); g.fill(polygon); if (border != null) { g.setStroke(new BasicStroke(0.3f)); g.setPaint(border); g.draw(polygon); } } else { System.out.printf("fillPolygon: type=%d, xpolys.length=%d\n", type, xpolys.length); } }
org.jhotdraw.geom.Polygon2D はあるようだが、標準APIにはなさそう。 別の方法で int[] を float[] に変えられないか検討したい。
下の図ではタイル境界線でラインにわずかな「ずれ」がある。
この問題は使用APIを変更して、座標値を int から float に変えることにより解決した。