/*
* Copyright 2012 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.renderer;
import org.oscim.backend.canvas.Color;
import org.oscim.backend.canvas.Paint.Cap;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tile;
import org.oscim.renderer.bucket.LineBucket;
import org.oscim.renderer.bucket.TextBucket;
import org.oscim.renderer.bucket.TextItem;
import org.oscim.theme.styles.LineStyle;
import org.oscim.theme.styles.TextStyle;
public class GridRenderer extends BucketRenderer {
private final TextBucket mTextBucket;
private final TextStyle mText;
private final LineBucket mLineBucket;
private final GeometryBuffer mLines;
private final StringBuilder mStringBuffer;
private int mCurX, mCurY, mCurZ;
public GridRenderer() {
this(1, new LineStyle(Color.LTGRAY, 1.2f, Cap.BUTT),
TextStyle.builder()
.fontSize(22)
.color(Color.RED)
.build());
}
public GridRenderer(int numLines, LineStyle lineStyle, TextStyle textStyle) {
int size = Tile.SIZE;
/* not needed to set but we know: 16 lines 'a' two points */
mLines = new GeometryBuffer(2 * 16, 16);
float pos = -size * 4;
/* 8 vertical lines */
for (int i = 0; i < 8 * numLines; i++) {
float x = pos + i * size / numLines;
mLines.startLine();
mLines.addPoint(x, pos);
mLines.addPoint(x, pos + size * 8);
}
/* 8 horizontal lines */
for (int j = 0; j < 8 * numLines; j++) {
float y = pos + j * size / numLines;
mLines.startLine();
mLines.addPoint(pos, y);
mLines.addPoint(pos + size * 8, y);
}
mText = textStyle;
mLineBucket = new LineBucket(0);
mLineBucket.line = lineStyle;
if (mText != null) {
mTextBucket = new TextBucket();
mTextBucket.next = mLineBucket;
} else {
mTextBucket = null;
mLineBucket.addLine(mLines);
buckets.set(mLineBucket);
}
mStringBuffer = new StringBuilder(32);
}
private void addLabels(int x, int y, int z) {
int s = Tile.SIZE;
TextBucket tl = mTextBucket;
tl.clear();
StringBuilder sb = mStringBuffer;
for (int yy = -2; yy < 2; yy++) {
for (int xx = -2; xx < 2; xx++) {
sb.setLength(0);
sb.append(x + xx)
.append(" / ")
.append(y + yy)
.append(" / ")
.append(z);
TextItem ti = TextItem.pool.get();
ti.set(s * xx + s / 2, s * yy + s / 2, sb.toString(), mText);
tl.addText(ti);
}
}
}
@Override
public void update(GLViewport v) {
/* scale coordinates relative to current 'zoom-level' to
* get the position as the nearest tile coordinate */
int z = 1 << v.pos.zoomLevel;
int x = (int) (v.pos.x * z);
int y = (int) (v.pos.y * z);
/* update buckets when map moved by at least one tile */
if (x == mCurX && y == mCurY && z == mCurZ)
return;
mCurX = x;
mCurY = y;
mCurZ = z;
mMapPosition.copy(v.pos);
mMapPosition.x = (double) x / z;
mMapPosition.y = (double) y / z;
mMapPosition.scale = z;
if (mText != null) {
buckets.set(mTextBucket);
addLabels(x, y, v.pos.zoomLevel);
mLineBucket.addLine(mLines);
buckets.prepare();
setReady(false);
}
if (!isReady())
compile();
}
}