/*
* Copyright 2010, 2011, 2012 mapsforge.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.mapsforge.android.maps.mapgenerator.databaserenderer;
import java.util.List;
import android.graphics.Bitmap;
import android.graphics.Paint;
final class WayDecorator {
/**
* Minimum distance in pixels before the symbol is repeated.
*/
private static final int DISTANCE_BETWEEN_SYMBOLS = 200;
/**
* Minimum distance in pixels before the way name is repeated.
*/
private static final int DISTANCE_BETWEEN_WAY_NAMES = 500;
/**
* Distance in pixels to skip from both ends of a segment.
*/
private static final int SEGMENT_SAFETY_DISTANCE = 30;
static void renderSymbol(Bitmap symbolBitmap, boolean alignCenter, boolean repeatSymbol, float[][] coordinates,
List<SymbolContainer> waySymbols) {
int skipPixels = SEGMENT_SAFETY_DISTANCE;
// get the first way point coordinates
float previousX = coordinates[0][0];
float previousY = coordinates[0][1];
// draw the symbol on each way segment
float segmentLengthRemaining;
float segmentSkipPercentage;
float symbolAngle;
for (int i = 2; i < coordinates[0].length; i += 2) {
// get the current way point coordinates
float currentX = coordinates[0][i];
float currentY = coordinates[0][i + 1];
// calculate the length of the current segment (Euclidian distance)
float diffX = currentX - previousX;
float diffY = currentY - previousY;
double segmentLengthInPixel = Math.sqrt(diffX * diffX + diffY * diffY);
segmentLengthRemaining = (float) segmentLengthInPixel;
while (segmentLengthRemaining - skipPixels > SEGMENT_SAFETY_DISTANCE) {
// calculate the percentage of the current segment to skip
segmentSkipPercentage = skipPixels / segmentLengthRemaining;
// move the previous point forward towards the current point
previousX += diffX * segmentSkipPercentage;
previousY += diffY * segmentSkipPercentage;
symbolAngle = (float) Math.toDegrees(Math.atan2(currentY - previousY, currentX - previousX));
waySymbols.add(new SymbolContainer(symbolBitmap, previousX, previousY, alignCenter, symbolAngle));
// check if the symbol should only be rendered once
if (!repeatSymbol) {
return;
}
// recalculate the distances
diffX = currentX - previousX;
diffY = currentY - previousY;
// recalculate the remaining length of the current segment
segmentLengthRemaining -= skipPixels;
// set the amount of pixels to skip before repeating the symbol
skipPixels = DISTANCE_BETWEEN_SYMBOLS;
}
skipPixels -= segmentLengthRemaining;
if (skipPixels < SEGMENT_SAFETY_DISTANCE) {
skipPixels = SEGMENT_SAFETY_DISTANCE;
}
// set the previous way point coordinates for the next loop
previousX = currentX;
previousY = currentY;
}
}
static void renderText(String textKey, Paint paint, Paint outline, float[][] coordinates,
List<WayTextContainer> wayNames) {
// calculate the way name length plus some margin of safety
float wayNameWidth = paint.measureText(textKey) + 10;
int skipPixels = 0;
// get the first way point coordinates
float previousX = coordinates[0][0];
float previousY = coordinates[0][1];
// find way segments long enough to draw the way name on them
for (int i = 2; i < coordinates[0].length; i += 2) {
// get the current way point coordinates
float currentX = coordinates[0][i];
float currentY = coordinates[0][i + 1];
// calculate the length of the current segment (Euclidian distance)
float diffX = currentX - previousX;
float diffY = currentY - previousY;
double segmentLengthInPixel = Math.sqrt(diffX * diffX + diffY * diffY);
if (skipPixels > 0) {
skipPixels -= segmentLengthInPixel;
} else if (segmentLengthInPixel > wayNameWidth) {
float[] wayNamePath = new float[4];
// check to prevent inverted way names
if (previousX <= currentX) {
wayNamePath[0] = previousX;
wayNamePath[1] = previousY;
wayNamePath[2] = currentX;
wayNamePath[3] = currentY;
} else {
wayNamePath[0] = currentX;
wayNamePath[1] = currentY;
wayNamePath[2] = previousX;
wayNamePath[3] = previousY;
}
wayNames.add(new WayTextContainer(wayNamePath, textKey, paint));
if (outline != null) {
wayNames.add(new WayTextContainer(wayNamePath, textKey, outline));
}
skipPixels = DISTANCE_BETWEEN_WAY_NAMES;
}
// store the previous way point coordinates
previousX = currentX;
previousY = currentY;
}
}
private WayDecorator() {
throw new IllegalStateException();
}
}