標準OSM地図では、 崖(natural=cliff)は下図に示すように、折れ線に沿って、小さな三角画像(▲)を高い方から低い方に向けて 描き並べる。
Javaでこれに相当することを行う。
三角と三角の間は少し隙間があり、この間隔は多少調整できる。折れ線は短い直線がつながったものである。
画像幅より短い線分には画像は描かず、それより長い線分には隙間を調整して、整数個の画像を描くものと する。
標準OSM地図ではもっと細かい処理が行われているようであり、画像の描画が途中で終わり、次の線分では 残りの描画を行っているケースもあるようだ。その場合、隣り合う線分は平行ではないため、 小さな三角は形が崩れる。
標準OSM地図より多少見栄えは落ちてもいいので、プログラムを簡単にしたい。
Android Java では次のようにしている。 まずは、これを本家Javaに置き換えたい。
イメージの回転は Matrix が AffineTransform に代わるが、本質的には大差がないであろう。
void drawIconMulti(Canvas canvas, Renderer r, Bitmap bmp, float space) { if (bmp == null) return; float width = bmp.getWidth(); float height = bmp.getHeight(); Matrix matrix = r.matrixMultiIcon; float prv_x = points[0], prv_y = points[1]; for (int k = 1; k < points.length/2; k++) { float x = points[k * 2]; float y = points[k * 2 + 1]; double dist = distance(x, y, prv_x, prv_y); int num_icons = (int)(dist / (width + space) + 0.5); float dx = (x - prv_x) / num_icons; float dy = (y - prv_y) / num_icons; float deg = (float)degree(prv_x, prv_y, x, y); float x1 = prv_x, y1 = prv_y; for (int n = 0; n++ < num_icons; x1 += dx, y1 += dy) { matrix.reset(); matrix.postRotate(deg, width/2, height/2); matrix.postTranslate(x1+dx/2-width/2, y1+dy/2-height/2); canvas.drawBitmap(bmp, matrix, null); } prv_x = x1; prv_y = y1; } }
スクショを下に示す。パソコンの場合タイル画像のサイズは 256x256画素であるが、スマホは解像度が高いため 縦横3倍の768x768画素としている。このため、画像はパソコンよりも鮮明である。
void drawIconMulti(Graphics2D g, Image img, float space) { if (img == null) return; float width = img.getWidth(null); float height = img.getHeight(null); if (width <= 0 || height <= 0) return; float prv_x = xpoints[0], prv_y = ypoints[0]; for (int k = 1; k < xpoints.length; k++) { float x = xpoints[k]; float y = ypoints[k]; float dx = x - prv_x; float dy = y - prv_y; double dist = Math.hypot(dx, dy); double angle = Math.atan2(dy, dx); int num = (int)(dist / (width + space) + 0.5); float x1 = prv_x, y1 = prv_y; for (int n = 0; n++ < num; x1 += dx/num, y1 += dy/num) { AffineTransform affin = new AffineTransform(); affin.translate(x1-width/2, y1-height/2); //イメージの移動 affin.rotate(angle, width/2, height/2); //画像の中心に回転 g.drawImage(img, affin, null); //イメージの描画 } prv_x = x1; prv_y = y1; } }