package aimax.osm.viewer; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; /** * Defines a base class for scalable vector graphic icons. * @author Ruediger Lunde * */ public abstract class EntityIcon { protected float size; public float size() { return size; } public abstract void draw(Graphics2D g2, int x, int y, float displayFactor); ///////////////////////////////////////////////////////////////// // implementation classes protected static BasicStroke currStroke; protected static BasicStroke currStroke2; protected static float currDisplayFactor; protected static BasicStroke getStroke(float displayFactor, boolean s2) { if (displayFactor != currDisplayFactor) { currStroke = new BasicStroke(displayFactor); currStroke2 = new BasicStroke(2f*displayFactor); currDisplayFactor = displayFactor; } return s2 ? currStroke2 : currStroke; } /** * Implements a universally usable icon, consisting of a primitive shape * and a character symbol inside. * @author Ruediger Lunde */ public static class SimpleIcon extends EntityIcon { public static enum Shape { CIRCLE, RECTANGLE, TRIANGLE, NONE } Shape shape; String symbol; Color lineColor; Color fillColor; Color symColor; public SimpleIcon(Shape shape, float size, String symbol, Color line, Color fill, Color sym) { this.shape = shape; this.size = size; this.symbol = symbol; lineColor = line; fillColor = fill; symColor = sym; } public void draw(Graphics2D g2, int x, int y, float displayFactor) { int dsize = Math.round(size * displayFactor); int offset = Math.round(size * displayFactor / 2f); x -= offset; y -= offset; g2.setStroke(getStroke(displayFactor, false)); if (fillColor != null) { g2.setColor(fillColor); switch (shape) { case CIRCLE: g2.fillOval(x, y, dsize, dsize); break; case RECTANGLE: g2.fillRect(x, y, dsize, dsize); break; case TRIANGLE: g2.fillPolygon( new int[] {x, x+dsize, x+offset, x}, new int[] {y+dsize, y+dsize, y, y+dsize}, 4); break; default: break; } } if (lineColor != null && !lineColor.equals(fillColor)) { g2.setColor(lineColor); g2.setStroke(getStroke(displayFactor, true)); switch (shape) { case CIRCLE: g2.drawOval(x, y, dsize, dsize); break; case RECTANGLE: g2.drawRect(x, y, dsize, dsize); break; case TRIANGLE: g2.drawPolygon( new int[] {x, x+dsize, x+offset, x}, new int[] {y+dsize, y+dsize, y, y+dsize}, 4); break; default: break; } } if (symbol != null) { Font font = g2.getFont(); g2.setColor(symColor); g2.setFont(font.deriveFont((size-2)*displayFactor)); g2.drawString(symbol, x+2.5f*displayFactor, y+dsize-2f*displayFactor); g2.setFont(font); } } } /** * Special icon representing a pin (used for markers on the map). * @author Ruediger Lunde */ public static class PinIcon extends EntityIcon { Color lineColor; Color fillColor; public PinIcon(float size, Color line, Color fill) { this.size = size; this.lineColor = line; this.fillColor = fill; } public void draw(Graphics2D g2, int x, int y, float displayFactor) { int dsize = Math.round(size * displayFactor); g2.setStroke(getStroke(displayFactor, true)); g2.setColor(lineColor); g2.drawLine(x, y, x+dsize, y-dsize); g2.setStroke(getStroke(displayFactor, false)); int l = dsize/3+1; g2.setColor(fillColor); l = dsize/3+1; g2.fillOval(x+dsize-l, y-dsize-l, 2*l, 2*l); } } /** * Special icon representing a church. * @author Ruediger Lunde */ public static class ChurchIcon extends EntityIcon { Color lineColor; Color fillColor; public ChurchIcon(float size, Color line, Color fill) { this.size = size; this.lineColor = line; this.fillColor = fill; } public void draw(Graphics2D g2, int x, int y, float displayFactor) { int dsize = Math.round(size * displayFactor); int offset = Math.round(size * displayFactor / 2f); x -= offset; y -= offset; g2.setStroke(getStroke(displayFactor, false)); g2.setColor(fillColor); g2.fillOval(x, y, dsize, dsize); g2.setColor(lineColor); g2.drawOval(x, y, dsize, dsize); g2.drawLine(x+offset, y, x+offset, y-dsize/2); g2.drawLine(x+offset/2, (int)y-offset/2, x+offset*3/2, y-offset/2); } } /** * Special icon representing a castle. * @author Ruediger Lunde */ public static class CastleIcon extends EntityIcon { Color lineColor; Color fillColor; public CastleIcon(float size, Color line, Color fill) { this.size = size; this.lineColor = line; this.fillColor = fill; } public void draw(Graphics2D g2, int x, int y, float displayFactor) { int dsize = Math.round(size * displayFactor); int offset = Math.round(size * displayFactor / 2f); int[] xCoords = new int[] {x+offset, x+dsize, x+offset*2/3}; int[] yCoords = new int[] {y-dsize, y-dsize, y-dsize*2/3}; g2.setStroke(getStroke(displayFactor, false)); g2.setColor(fillColor); g2.fillPolygon(xCoords, yCoords, 3); g2.setColor(lineColor); g2.drawPolygon(xCoords, yCoords, 3); g2.drawLine(x, y, x+offset, y-dsize); g2.setColor(fillColor); g2.fillOval(x-offset, y-offset, dsize, dsize); g2.setColor(lineColor); g2.drawOval(x-offset, y-offset, dsize, dsize); } } /** * Special icon representing a camp site. * @author Ruediger Lunde */ public static class TentIcon extends EntityIcon { Color lineColor; Color fillColor; public TentIcon(float size, Color line, Color fill) { this.size = size; lineColor = line; fillColor = fill; } public void draw(Graphics2D g2, int x, int y, float displayFactor) { int dsize = Math.round(size * displayFactor); int offset = Math.round(size * displayFactor / 2f); x -= offset; y -= offset; g2.setColor(fillColor); g2.setStroke(getStroke(displayFactor, false)); g2.fillPolygon( new int[] {x, x+dsize, x+offset, x}, new int[] {y+dsize, y+dsize, y, y+dsize}, 4); g2.setColor(lineColor); //g2.setStroke(getStroke(displayFactor, true)); g2.drawPolyline( new int[] {x+offset+offset/2, x, x+dsize, x+offset-offset/2}, new int[] {y-offset/2, y+dsize, y+dsize, y-offset/2}, 4); } } }