/* Copyright 2013 Malcolm Herring * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * For a copy of the GNU General Public License, see . */ package seamap; import java.awt.*; import java.awt.geom.*; import java.util.*; import s57.S57att.*; import s57.S57obj.*; import s57.S57val.*; import s57.S57val; import seamap.SeaMap; import seamap.SeaMap.*; import seamap.SeaMap.Area; import symbols.Symbols; import symbols.Symbols.*; public class Renderer { static MapHelper helper; static SeaMap map; static double sScale; static double tScale; static Graphics2D g2; static int zoom; public static void reRender(Graphics2D g, int z, double factor, SeaMap m, MapHelper h) { g2 = g; zoom = z; helper = h; map = m; sScale = Symbols.symbolScale[zoom]*factor; tScale = Symbols.textScale[zoom]*factor; if (map != null) { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); Rules.rules(map, zoom); } } public static AttMap getAtts(Feature feature, Obj obj, int idx) { HashMap objs = feature.objs.get(obj); if (objs == null) return null; else return objs.get(idx); } public static Object getAttVal(Feature feature, Obj obj, int idx, Att att) { AttMap atts = getAtts(feature, obj, idx); if (atts == null) return S57val.nullVal(att); else { AttItem item = atts.get(att); if (item == null) return S57val.nullVal(att); return item.val; } } public static void symbol(Feature feature, Symbol symbol, Obj obj, Delta delta) { Point2D point = helper.getPoint(feature.centre); if (obj == null) { Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), delta, null); } else { ArrayList colours = (ArrayList) getAttVal(feature, obj, 0, Att.COLOUR); ArrayList pattern = (ArrayList) getAttVal(feature, obj, 0, Att.COLPAT); Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), delta, new Scheme(pattern, colours)); } } private static Rectangle symbolSize(Symbol symbol) { Symbol ssymb = symbol; while (ssymb != null) { for (Instr item : symbol) { if (item.type == Prim.BBOX) { return (Rectangle) item.params; } if (item.type == Prim.SYMB) { ssymb = ((SubSymbol)item.params).instr; break; } } if (ssymb == symbol) break; } return null; } public static void lineSymbols(Feature feature, Symbol prisymb, double space, Symbol secsymb, int ratio) { Area area; switch (feature.flag) { case LINE: Edge edge = map.edges.get(feature.refs); area = map.new Area(); area.add(map.new Bound(map.new Side(edge, true), true)); break; case AREA: area = map.areas.get(feature.refs); break; default: return; } Rectangle prect = symbolSize(prisymb); Rectangle srect = symbolSize(secsymb); if (srect == null) ratio = 0; if (prect != null) { double psize = Math.abs(prect.getY()) * sScale; double ssize = (srect != null) ? Math.abs(srect.getY()) * sScale : 0; Point2D prev = new Point2D.Double(); Point2D next = new Point2D.Double(); Point2D curr = new Point2D.Double(); Point2D succ = new Point2D.Double(); boolean gap = true; boolean piv = false; double len = 0; double angle = 0; int scount = ratio; Symbol symbol = prisymb; for (Bound bound : area) { BoundIterator bit = map.new BoundIterator(bound); boolean first = true; while (bit.hasNext()) { prev = next; next = helper.getPoint(bit.next()); angle = Math.atan2(next.getY() - prev.getY(), next.getX() - prev.getX()); piv = true; if (first) { curr = succ = next; gap = (space > 0); scount = ratio; symbol = prisymb; len = gap ? psize * space * 0.5 : psize; first = false; } else { while (curr.distance(next) >= len) { if (piv) { double rem = len; double s = prev.distance(next); double p = curr.distance(prev); if ((s > 0) && (p > 0)) { double n = curr.distance(next); double theta = Math.acos((s * s + p * p - n * n) / 2 / s / p); double phi = Math.asin(p / len * Math.sin(theta)); rem = len * Math.sin(Math.PI - theta - phi) / Math.sin(theta); } succ = new Point2D.Double(prev.getX() + (rem * Math.cos(angle)), prev.getY() + (rem * Math.sin(angle))); piv = false; } else { succ = new Point2D.Double(curr.getX() + (len * Math.cos(angle)), curr.getY() + (len * Math.sin(angle))); } if (!gap) { Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX()) + Math.toRadians(90)))), null); } if (space > 0) gap = !gap; curr = succ; len = gap ? (psize * space) : (--scount == 0) ? ssize : psize; if (scount == 0) { symbol = secsymb; scount = ratio; } else { symbol = prisymb; } } } } } } } public static void lineVector (Feature feature, LineStyle style) { Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD); Point2D point; switch (feature.flag) { case LINE: EdgeIterator eit = map.new EdgeIterator(map.edges.get(feature.refs), true); point = helper.getPoint(eit.next()); p.moveTo(point.getX(), point.getY()); while (eit.hasNext()) { point = helper.getPoint(eit.next()); p.lineTo(point.getX(), point.getY()); } break; case AREA: for (Bound bound : map.areas.get(feature.refs)) { BoundIterator bit = map.new BoundIterator(bound); point = helper.getPoint(bit.next()); p.moveTo(point.getX(), point.getY()); while (bit.hasNext()) { point = helper.getPoint(bit.next()); p.lineTo(point.getX(), point.getY()); } } break; } if (style.line != null) { if (style.dash != null) { float[] dash = new float[style.dash.length]; System.arraycopy(style.dash, 0, dash, 0, style.dash.length); for (int i = 0; i < style.dash.length; i++) { dash[i] *= (float) sScale; } g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1, dash, 0)); } else { g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); } g2.setPaint(style.line); g2.draw(p); } if (style.fill != null) { g2.setPaint(style.fill); g2.fill(p); } } public static void labelText (Feature feature, String str, Font font, Color colour, Delta delta) { Symbol label = new Symbol(); label.add(new Instr(Prim.TEXT, new Caption(str, font, colour, (delta == null) ? new Delta(Handle.CC, null) : delta))); Point2D point = helper.getPoint(feature.centre); Symbols.drawSymbol(g2, label, tScale, point.getX(), point.getY(), null, null); } public static void lineText (Feature feature, String str, Font font, double offset, double dy) { } }