- Timestamp:
- 2012-11-07T19:32:09+01:00 (12 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 1 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/AbstractMapRenderer.java
r4087 r5571 2 2 package org.openstreetmap.josm.data.osm.visitor.paint; 3 3 4 import java.awt.Color; 4 5 import java.awt.Graphics2D; 5 6 import java.awt.Point; 7 import java.awt.geom.GeneralPath; 8 import java.awt.geom.Point2D; 9 import java.util.Iterator; 10 11 import org.openstreetmap.josm.Main; 12 import org.openstreetmap.josm.data.osm.BBox; 13 import org.openstreetmap.josm.data.osm.DataSet; 14 import org.openstreetmap.josm.data.osm.Node; 15 import org.openstreetmap.josm.data.osm.Way; 16 import org.openstreetmap.josm.data.osm.WaySegment; 6 17 import org.openstreetmap.josm.gui.NavigatableComponent; 7 18 import org.openstreetmap.josm.tools.CheckParameterUtil; … … 17 28 /** the map viewport - provides projection and hit detection functionality */ 18 29 protected NavigatableComponent nc; 30 19 31 /** if true, the paint visitor shall render OSM objects such that they 20 * look inactive. Example: rendering of data in an inactive layer using light gray as color only. 21 */ 32 * look inactive. Example: rendering of data in an inactive layer using light gray as color only. */ 22 33 protected boolean isInactiveMode; 23 34 /** Color Preference for background */ 35 protected Color backgroundColor; 36 /** Color Preference for inactive objects */ 37 protected Color inactiveColor; 38 /** Color Preference for selected objects */ 39 protected Color selectedColor; 40 /** Color Preference for nodes */ 41 protected Color nodeColor; 42 43 /** Color Preference for hightlighted objects */ 44 protected Color highlightColor; 45 /** Preference: size of virtual nodes (0 displayes display) */ 46 protected int virtualNodeSize; 47 /** Preference: minimum space (displayed way length) to display virtual nodes */ 48 protected int virtualNodeSpace; 49 50 /** Preference: minimum space (displayed way length) to display segment numbers */ 51 protected int segmentNumberSpace; 52 24 53 /** 25 54 * <p>Creates an abstract paint visitor</p> … … 39 68 this.isInactiveMode = isInactiveMode; 40 69 } 70 71 /** 72 * Draw the node as small rectangle with the given color. 73 * 74 * @param n The node to draw. 75 * @param color The color of the node. 76 */ 77 public abstract void drawNode(Node n, Color color, int size, boolean fill); 78 79 /** 80 * Draw an number of the order of the two consecutive nodes within the 81 * parents way 82 * 83 * @param p1 First point of the way segment. 84 * @param p2 Second point of the way segment. 85 * @param orderNumber The number of the segment in the way. 86 */ 87 protected void drawOrderNumber(Point p1, Point p2, int orderNumber, Color clr) { 88 if (isSegmentVisible(p1, p2) && isLargeSegment(p1, p2, segmentNumberSpace)) { 89 String on = Integer.toString(orderNumber); 90 int strlen = on.length(); 91 int x = (p1.x+p2.x)/2 - 4*strlen; 92 int y = (p1.y+p2.y)/2 + 4; 93 94 if (virtualNodeSize != 0 && isLargeSegment(p1, p2, virtualNodeSpace)) { 95 y = (p1.y+p2.y)/2 - virtualNodeSize - 3; 96 } 97 98 g.setColor(backgroundColor); 99 g.fillRect(x-1, y-12, 8*strlen+1, 14); 100 g.setColor(clr); 101 g.drawString(on, x, y); 102 } 103 } 104 105 /** 106 * Draws virtual nodes. 107 * 108 * @param data The data set being rendered. 109 * @param bbox The bounding box being displayed. 110 */ 111 public void drawVirtualNodes(DataSet data, BBox bbox) { 112 if (virtualNodeSize == 0 || data == null || bbox == null) 113 return; 114 // print normal virtual nodes 115 GeneralPath path = new GeneralPath(); 116 for (Way osm : data.searchWays(bbox)) { 117 if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) { 118 visitVirtual(path, osm); 119 } 120 } 121 g.setColor(nodeColor); 122 g.draw(path); 123 try { 124 // print highlighted virtual nodes. Since only the color changes, simply 125 // drawing them over the existing ones works fine (at least in their current 126 // simple style) 127 path = new GeneralPath(); 128 for (WaySegment wseg: data.getHighlightedVirtualNodes()) { 129 if (wseg.way.isUsable() && !wseg.way.isDisabled()) { 130 visitVirtual(path, wseg.toWay()); 131 } 132 } 133 g.setColor(highlightColor); 134 g.draw(path); 135 } catch (ArrayIndexOutOfBoundsException e) { 136 // Silently ignore any ArrayIndexOutOfBoundsException that may be raised 137 // if the way has changed while being rendered (fix #7979) 138 // TODO: proper solution ? 139 // Idea from bastiK: avoid the WaySegment class and add another data class with { Way way; Node firstNode, secondNode; int firstIdx; }. 140 // On read, it would first check, if the way still has firstIdx+2 nodes, then check if the corresponding way nodes are still the same 141 // and report changes in a more controlled manner. 142 } 143 } 144 145 /** 146 * Reads the color definitions from preferences. This function is <code>public</code>, so that 147 * color names in preferences can be displayed even without calling the wireframe display before. 148 */ 149 public void getColors() { 150 this.backgroundColor = PaintColors.BACKGROUND.get(); 151 this.inactiveColor = PaintColors.INACTIVE.get(); 152 this.selectedColor = PaintColors.SELECTED.get(); 153 this.nodeColor = PaintColors.NODE.get(); 154 this.highlightColor = PaintColors.HIGHLIGHT.get(); 155 } 156 157 /** 158 * Reads all the settings from preferences. Calls the @{link #getColors} 159 * function. 160 * 161 * @param virtual <code>true</code> if virtual nodes are used 162 */ 163 protected void getSettings(boolean virtual) { 164 this.virtualNodeSize = virtual ? Main.pref.getInteger("mappaint.node.virtual-size", 8) / 2 : 0; 165 this.virtualNodeSpace = Main.pref.getInteger("mappaint.node.virtual-space", 70); 166 this.segmentNumberSpace = Main.pref.getInteger("mappaint.segmentnumber.space", 40); 167 getColors(); 168 } 169 170 /** 171 * Checks if a way segemnt is large enough for additional information display. 172 * 173 * @param p1 First point of the way segment. 174 * @param p2 Second point of the way segment. 175 * @param space The free space to check against. 176 * @return <code>true</code> if segment is larger than required space 177 */ 178 public static boolean isLargeSegment(Point2D p1, Point2D p2, int space) { 179 double xd = Math.abs(p1.getX()-p2.getX()); 180 double yd = Math.abs(p1.getY()-p2.getY()); 181 return (xd+yd > space); 182 } 183 184 /** 185 * Checks if segment is visible in display. 186 * 187 * @param p1 First point of the way segment. 188 * @param p2 Second point of the way segment. 189 * @return <code>true</code> if segment is visible. 190 */ 191 protected boolean isSegmentVisible(Point p1, Point p2) { 192 if ((p1.x < 0) && (p2.x < 0)) return false; 193 if ((p1.y < 0) && (p2.y < 0)) return false; 194 if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false; 195 if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false; 196 return true; 197 } 198 199 /** 200 * Creates path for drawing virtual nodes for one way. 201 * 202 * @param path The path to append drawing to. 203 * @param w The ways to draw node for. 204 */ 205 public void visitVirtual(GeneralPath path, Way w) { 206 Iterator<Node> it = w.getNodes().iterator(); 207 if (it.hasNext()) { 208 Point lastP = nc.getPoint(it.next()); 209 while (it.hasNext()) 210 { 211 Point p = nc.getPoint(it.next()); 212 if (isSegmentVisible(lastP, p) && isLargeSegment(lastP, p, virtualNodeSpace)) 213 { 214 int x = (p.x+lastP.x)/2; 215 int y = (p.y+lastP.y)/2; 216 path.moveTo(x-virtualNodeSize, y); 217 path.lineTo(x+virtualNodeSize, y); 218 path.moveTo(x, y-virtualNodeSize); 219 path.lineTo(x, y+virtualNodeSize); 220 } 221 lastP = p; 222 } 223 } 224 } 41 225 } -
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
r5217 r5571 2 2 package org.openstreetmap.josm.data.osm.visitor.paint; 3 3 4 import java.awt.AlphaComposite; 5 import java.awt.BasicStroke; 6 import java.awt.Color; 7 import java.awt.Font; 8 import java.awt.FontMetrics; 4 9 import java.awt.Graphics2D; 10 import java.awt.Image; 11 import java.awt.Point; 12 import java.awt.Polygon; 13 import java.awt.Rectangle; 5 14 import java.awt.RenderingHints; 15 import java.awt.Shape; 16 import java.awt.TexturePaint; 17 import java.awt.font.FontRenderContext; 18 import java.awt.font.GlyphVector; 19 import java.awt.font.LineMetrics; 20 import java.awt.geom.AffineTransform; 21 import java.awt.geom.GeneralPath; 22 import java.awt.geom.Path2D; 23 import java.awt.geom.Point2D; 24 import java.awt.geom.Rectangle2D; 6 25 import java.util.ArrayList; 26 import java.util.Arrays; 7 27 import java.util.Collection; 8 28 import java.util.Collections; 29 import java.util.Iterator; 9 30 import java.util.List; 31 32 import javax.swing.ImageIcon; 10 33 11 34 import org.openstreetmap.josm.Main; 12 35 import org.openstreetmap.josm.data.Bounds; 36 import org.openstreetmap.josm.data.coor.EastNorth; 13 37 import org.openstreetmap.josm.data.osm.BBox; 14 38 import org.openstreetmap.josm.data.osm.DataSet; 15 39 import org.openstreetmap.josm.data.osm.Node; 16 40 import org.openstreetmap.josm.data.osm.OsmPrimitive; 41 import org.openstreetmap.josm.data.osm.OsmUtils; 17 42 import org.openstreetmap.josm.data.osm.Relation; 43 import org.openstreetmap.josm.data.osm.RelationMember; 18 44 import org.openstreetmap.josm.data.osm.Way; 19 45 import org.openstreetmap.josm.data.osm.WaySegment; 46 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon; 47 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData; 48 import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache; 20 49 import org.openstreetmap.josm.gui.NavigatableComponent; 21 50 import org.openstreetmap.josm.gui.mappaint.AreaElemStyle; 51 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle; 52 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.HorizontalTextAlignment; 53 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.VerticalTextAlignment; 22 54 import org.openstreetmap.josm.gui.mappaint.ElemStyle; 23 55 import org.openstreetmap.josm.gui.mappaint.ElemStyles; 56 import org.openstreetmap.josm.gui.mappaint.MapImage; 24 57 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles; 25 58 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle; 59 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.Symbol; 26 60 import org.openstreetmap.josm.gui.mappaint.StyleCache.StyleList; 61 import org.openstreetmap.josm.gui.mappaint.TextElement; 62 import org.openstreetmap.josm.tools.ImageProvider; 63 import org.openstreetmap.josm.tools.Pair; 64 import org.openstreetmap.josm.tools.Utils; 27 65 28 66 /** … … 30 68 * 31 69 */ 32 public class StyledMapRenderer extends AbstractMapRenderer{ 33 34 private ElemStyles styles; 35 private double circum; 36 private MapPainter painter; 37 private MapPaintSettings paintSettings; 38 39 private static int FLAG_NORMAL = 0; 40 private static int FLAG_DISABLED = 1; 41 private static int FLAG_MEMBER_OF_SELECTED = 2; 42 private static int FLAG_SELECTED = 4; 43 44 private static class StyleRecord implements Comparable<StyleRecord> { 45 final ElemStyle style; 46 final OsmPrimitive osm; 47 final int flags; 48 49 public StyleRecord(ElemStyle style, OsmPrimitive osm, int flags) { 50 this.style = style; 51 this.osm = osm; 52 this.flags = flags; 70 public class StyledMapRenderer extends AbstractMapRenderer { 71 72 /** 73 * Iterates over a list of Way Nodes and returns screen coordinates that 74 * represent a line that is shifted by a certain offset perpendicular 75 * to the way direction. 76 * 77 * There is no intention, to handle consecutive duplicate Nodes in a 78 * perfect way, but it is should not throw an exception. 79 */ 80 private class OffsetIterator implements Iterator<Point> { 81 82 private List<Node> nodes; 83 private float offset; 84 private int idx; 85 86 private Point prev = null; 87 /* 'prev0' is a point that has distance 'offset' from 'prev' and the 88 * line from 'prev' to 'prev0' is perpendicular to the way segment from 89 * 'prev' to the next point. 90 */ 91 private int x_prev0, y_prev0; 92 93 public OffsetIterator(List<Node> nodes, float offset) { 94 this.nodes = nodes; 95 this.offset = offset; 96 idx = 0; 53 97 } 54 98 55 99 @Override 56 public int compareTo(StyleRecord other) { 57 if ((this.flags & FLAG_DISABLED) != 0 && (other.flags & FLAG_DISABLED) == 0) 58 return -1; 59 if ((this.flags & FLAG_DISABLED) == 0 && (other.flags & FLAG_DISABLED) != 0) 60 return 1; 61 62 int d0 = Float.compare(this.style.major_z_index, other.style.major_z_index); 63 if (d0 != 0) 64 return d0; 65 66 // selected on top of member of selected on top of unselected 67 // FLAG_DISABLED bit is the same at this point 68 if (this.flags > other.flags) 69 return 1; 70 if (this.flags < other.flags) 71 return -1; 72 73 int dz = Float.compare(this.style.z_index, other.style.z_index); 74 if (dz != 0) 75 return dz; 76 77 // simple node on top of icons and shapes 78 if (this.style == NodeElemStyle.SIMPLE_NODE_ELEMSTYLE && other.style != NodeElemStyle.SIMPLE_NODE_ELEMSTYLE) 79 return 1; 80 if (this.style != NodeElemStyle.SIMPLE_NODE_ELEMSTYLE && other.style == NodeElemStyle.SIMPLE_NODE_ELEMSTYLE) 81 return -1; 82 83 // newer primitives to the front 84 long id = this.osm.getUniqueId() - other.osm.getUniqueId(); 85 if (id > 0) 86 return 1; 87 if (id < 0) 88 return -1; 89 90 return Float.compare(this.style.object_z_index, other.style.object_z_index); 100 public boolean hasNext() { 101 return idx < nodes.size(); 102 } 103 104 @Override 105 public Point next() { 106 if (Math.abs(offset) < 0.1f) return nc.getPoint(nodes.get(idx++)); 107 108 Point current = nc.getPoint(nodes.get(idx)); 109 110 if (idx == nodes.size() - 1) { 111 ++idx; 112 return new Point(x_prev0 + current.x - prev.x, y_prev0 + current.y - prev.y); 113 } 114 115 Point next = nc.getPoint(nodes.get(idx+1)); 116 117 int dx_next = next.x - current.x; 118 int dy_next = next.y - current.y; 119 double len_next = Math.sqrt(dx_next*dx_next + dy_next*dy_next); 120 121 if (len_next == 0) { 122 len_next = 1; // value does not matter, because dy_next and dx_next is 0 123 } 124 125 int x_current0 = current.x + (int) Math.round(offset * dy_next / len_next); 126 int y_current0 = current.y - (int) Math.round(offset * dx_next / len_next); 127 128 if (idx==0) { 129 ++idx; 130 prev = current; 131 x_prev0 = x_current0; 132 y_prev0 = y_current0; 133 return new Point(x_current0, y_current0); 134 } else { 135 int dx_prev = current.x - prev.x; 136 int dy_prev = current.y - prev.y; 137 138 // determine intersection of the lines parallel to the two 139 // segments 140 int det = dx_next*dy_prev - dx_prev*dy_next; 141 142 if (det == 0) { 143 ++idx; 144 prev = current; 145 x_prev0 = x_current0; 146 y_prev0 = y_current0; 147 return new Point(x_current0, y_current0); 148 } 149 150 int m = dx_next*(y_current0 - y_prev0) - dy_next*(x_current0 - x_prev0); 151 152 int cx_ = x_prev0 + Math.round((float)m * dx_prev / det); 153 int cy_ = y_prev0 + Math.round((float)m * dy_prev / det); 154 ++idx; 155 prev = current; 156 x_prev0 = x_current0; 157 y_prev0 = y_current0; 158 return new Point(cx_, cy_); 159 } 160 } 161 162 @Override 163 public void remove() { 164 throw new UnsupportedOperationException(); 91 165 } 92 166 } … … 109 183 StyleList sl = styles.get(osm, circum, nc); 110 184 for (ElemStyle s : sl) { 111 styleElems.add(new StyleRecord(s, osm, flags));112 }113 }114 115 public void add(Way osm, int flags) {116 StyleList sl = styles.get(osm, circum, nc);117 for (ElemStyle s : sl) {118 if (!(drawArea && (flags & FLAG_DISABLED) == 0) && s instanceof AreaElemStyle) {119 continue;120 }121 185 styleElems.add(new StyleRecord(s, osm, flags)); 122 186 } … … 134 198 } 135 199 200 public void add(Way osm, int flags) { 201 StyleList sl = styles.get(osm, circum, nc); 202 for (ElemStyle s : sl) { 203 if (!(drawArea && (flags & FLAG_DISABLED) == 0) && s instanceof AreaElemStyle) { 204 continue; 205 } 206 styleElems.add(new StyleRecord(s, osm, flags)); 207 } 208 } 209 136 210 public void drawAll() { 137 211 Collections.sort(styleElems); … … 140 214 r.osm, 141 215 paintSettings, 142 painter,216 StyledMapRenderer.this, 143 217 (r.flags & FLAG_SELECTED) != 0, 144 218 (r.flags & FLAG_MEMBER_OF_SELECTED) != 0 … … 147 221 } 148 222 } 223 224 private static class StyleRecord implements Comparable<StyleRecord> { 225 final ElemStyle style; 226 final OsmPrimitive osm; 227 final int flags; 228 229 public StyleRecord(ElemStyle style, OsmPrimitive osm, int flags) { 230 this.style = style; 231 this.osm = osm; 232 this.flags = flags; 233 } 234 235 @Override 236 public int compareTo(StyleRecord other) { 237 if ((this.flags & FLAG_DISABLED) != 0 && (other.flags & FLAG_DISABLED) == 0) 238 return -1; 239 if ((this.flags & FLAG_DISABLED) == 0 && (other.flags & FLAG_DISABLED) != 0) 240 return 1; 241 242 int d0 = Float.compare(this.style.major_z_index, other.style.major_z_index); 243 if (d0 != 0) 244 return d0; 245 246 // selected on top of member of selected on top of unselected 247 // FLAG_DISABLED bit is the same at this point 248 if (this.flags > other.flags) 249 return 1; 250 if (this.flags < other.flags) 251 return -1; 252 253 int dz = Float.compare(this.style.z_index, other.style.z_index); 254 if (dz != 0) 255 return dz; 256 257 // simple node on top of icons and shapes 258 if (this.style == NodeElemStyle.SIMPLE_NODE_ELEMSTYLE && other.style != NodeElemStyle.SIMPLE_NODE_ELEMSTYLE) 259 return 1; 260 if (this.style != NodeElemStyle.SIMPLE_NODE_ELEMSTYLE && other.style == NodeElemStyle.SIMPLE_NODE_ELEMSTYLE) 261 return -1; 262 263 // newer primitives to the front 264 long id = this.osm.getUniqueId() - other.osm.getUniqueId(); 265 if (id > 0) 266 return 1; 267 if (id < 0) 268 return -1; 269 270 return Float.compare(this.style.object_z_index, other.style.object_z_index); 271 } 272 } 273 274 private static Boolean IS_GLYPH_VECTOR_DOUBLE_TRANSLATION_BUG = null; 275 276 /** 277 * Check, if this System has the GlyphVector double translation bug. 278 * 279 * With this bug, <code>gv.setGlyphTransform(i, trfm)</code> has a different 280 * effect than on most other systems, namely the translation components 281 * ("m02" & "m12", {@link AffineTransform}) appear to be twice as large, as 282 * they actually are. The rotation is unaffected (scale & shear not tested 283 * so far). 284 * 285 * This bug has only been observed on Mac OS X, see #7841. 286 * 287 * @return true, if the GlyphVector double translation bug is present on 288 * this System 289 */ 290 public static boolean isGlyphVectorDoubleTranslationBug() { 291 if (IS_GLYPH_VECTOR_DOUBLE_TRANSLATION_BUG != null) 292 return IS_GLYPH_VECTOR_DOUBLE_TRANSLATION_BUG; 293 FontRenderContext frc = new FontRenderContext(null, false, false); 294 Font font = new Font("Dialog", Font.PLAIN, 12); 295 GlyphVector gv = font.createGlyphVector(frc, "x"); 296 gv.setGlyphTransform(0, AffineTransform.getTranslateInstance(1000, 1000)); 297 Shape shape = gv.getGlyphOutline(0); 298 // x is about 1000 on normal stystems and about 2000 when the bug occurs 299 int x = shape.getBounds().x; 300 IS_GLYPH_VECTOR_DOUBLE_TRANSLATION_BUG = x > 1500; 301 return IS_GLYPH_VECTOR_DOUBLE_TRANSLATION_BUG; 302 } 303 304 private ElemStyles styles; 305 private double circum; 306 307 private MapPaintSettings paintSettings; 308 309 private Color relationSelectedColor; 310 private Color highlightColorTransparent; 311 312 private static int FLAG_NORMAL = 0; 313 private static int FLAG_DISABLED = 1; 314 private static int FLAG_MEMBER_OF_SELECTED = 2; 315 private static int FLAG_SELECTED = 4; 316 317 private static final double PHI = Math.toRadians(20); 318 private static final double cosPHI = Math.cos(PHI); 319 private static final double sinPHI = Math.sin(PHI); 320 321 private Collection<WaySegment> highlightWaySegments; 322 323 private boolean useStrokes; 324 private boolean showNames; 325 private boolean showIcons; 326 private boolean isOutlineOnly; 327 328 private Font orderFont; 329 330 private boolean leftHandTraffic; 149 331 150 332 /** … … 153 335 public StyledMapRenderer(Graphics2D g, NavigatableComponent nc, boolean isInactiveMode) { 154 336 super(g, nc, isInactiveMode); 337 } 338 339 private Polygon buildPolygon(Point center, int radius, int sides) { 340 return buildPolygon(center, radius, sides, 0.0); 341 } 342 343 private Polygon buildPolygon(Point center, int radius, int sides, double rotation) { 344 Polygon polygon = new Polygon(); 345 for (int i = 0; i < sides; i++) { 346 double angle = ((2 * Math.PI / sides) * i) - rotation; 347 int x = (int) Math.round(center.x + radius * Math.cos(angle)); 348 int y = (int) Math.round(center.y + radius * Math.sin(angle)); 349 polygon.addPoint(x, y); 350 } 351 return polygon; 155 352 } 156 353 … … 171 368 } 172 369 370 private void collectRelationStyles(DataSet data, StyleCollector sc, BBox bbox) { 371 for (Relation r: data.searchRelations(bbox)) { 372 if (r.isDrawable()) { 373 if (r.isDisabled()) { 374 sc.add(r, FLAG_DISABLED); 375 } else if (data.isSelected(r)) { 376 sc.add(r, FLAG_SELECTED); 377 } else { 378 sc.add(r, FLAG_NORMAL); 379 } 380 } 381 } 382 } 383 173 384 private void collectWayStyles(DataSet data, StyleCollector sc, BBox bbox) { 174 385 for (final Way w : data.searchWays(bbox)) { … … 187 398 } 188 399 189 private void collectRelationStyles(DataSet data, StyleCollector sc, BBox bbox) { 190 for (Relation r: data.searchRelations(bbox)) { 191 if (r.isDrawable()) { 192 if (r.isDisabled()) { 193 sc.add(r, FLAG_DISABLED); 194 } else if (data.isSelected(r)) { 195 sc.add(r, FLAG_SELECTED); 400 private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows, GeneralPath onewayArrowsCasing, 401 Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) { 402 g.setColor(isInactiveMode ? inactiveColor : color); 403 if (useStrokes) { 404 g.setStroke(line); 405 } 406 g.draw(path); 407 408 if(!isInactiveMode && useStrokes && dashes != null) { 409 g.setColor(dashedColor); 410 g.setStroke(dashes); 411 g.draw(path); 412 } 413 414 if (orientationArrows != null) { 415 g.setColor(isInactiveMode ? inactiveColor : color); 416 g.setStroke(new BasicStroke(line.getLineWidth(), line.getEndCap(), BasicStroke.JOIN_MITER, line.getMiterLimit())); 417 g.draw(orientationArrows); 418 } 419 420 if (onewayArrows != null) { 421 g.setStroke(new BasicStroke(1, line.getEndCap(), BasicStroke.JOIN_MITER, line.getMiterLimit())); 422 g.fill(onewayArrowsCasing); 423 g.setColor(isInactiveMode ? inactiveColor : backgroundColor); 424 g.fill(onewayArrows); 425 } 426 427 if (useStrokes) { 428 g.setStroke(new BasicStroke()); 429 } 430 } 431 432 protected void drawArea(OsmPrimitive osm, Path2D.Double path, Color color, MapImage fillImage, TextElement text) { 433 434 Shape area = path.createTransformedShape(nc.getAffineTransform()); 435 436 if (!isOutlineOnly) { 437 if (fillImage == null) { 438 if (isInactiveMode) { 439 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.33f)); 440 } 441 g.setColor(color); 442 g.fill(area); 443 } else { 444 TexturePaint texture = new TexturePaint(fillImage.getImage(), 445 // new Rectangle(polygon.xpoints[0], polygon.ypoints[0], fillImage.getWidth(), fillImage.getHeight())); 446 new Rectangle(0, 0, fillImage.getWidth(), fillImage.getHeight())); 447 g.setPaint(texture); 448 Float alpha = Utils.color_int2float(fillImage.alpha); 449 if (alpha != 1f) { 450 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); 451 } 452 g.fill(area); 453 g.setPaintMode(); 454 } 455 } 456 457 if (text != null && isShowNames()) { 458 /* 459 * abort if we can't compose the label to be rendered 460 */ 461 if (text.labelCompositionStrategy == null) return; 462 String name = text.labelCompositionStrategy.compose(osm); 463 if (name == null) return; 464 465 Rectangle pb = area.getBounds(); 466 FontMetrics fontMetrics = g.getFontMetrics(orderFont); // if slow, use cache 467 Rectangle2D nb = fontMetrics.getStringBounds(name, g); // if slow, approximate by strlen()*maxcharbounds(font) 468 469 // Point2D c = getCentroid(polygon); 470 // Using the Centroid is Nicer for buildings like: +--------+ 471 // but this needs to be fast. As most houses are | 42 | 472 // boxes anyway, the center of the bounding box +---++---+ 473 // will have to do. ++ 474 // Centroids are not optimal either, just imagine a U-shaped house. 475 // Point2D c = new Point2D.Double(pb.x + pb.width / 2.0, pb.y + pb.height / 2.0); 476 // Rectangle2D.Double centeredNBounds = 477 // new Rectangle2D.Double(c.getX() - nb.getWidth()/2, 478 // c.getY() - nb.getHeight()/2, 479 // nb.getWidth(), 480 // nb.getHeight()); 481 482 Rectangle centeredNBounds = new Rectangle(pb.x + (int)((pb.width - nb.getWidth())/2.0), 483 pb.y + (int)((pb.height - nb.getHeight())/2.0), 484 (int)nb.getWidth(), 485 (int)nb.getHeight()); 486 487 if ((pb.width >= nb.getWidth() && pb.height >= nb.getHeight()) && // quick check 488 area.contains(centeredNBounds) // slow but nice 489 ) { 490 if (isInactiveMode || osm.isDisabled()) { 491 g.setColor(inactiveColor); 196 492 } else { 197 sc.add(r, FLAG_NORMAL); 198 } 199 } 200 } 493 g.setColor(text.color); 494 } 495 Font defaultFont = g.getFont(); 496 g.setFont (text.font); 497 g.drawString (name, 498 (int)(centeredNBounds.getMinX() - nb.getMinX()), 499 (int)(centeredNBounds.getMinY() - nb.getMinY())); 500 g.setFont(defaultFont); 501 } 502 } 503 } 504 505 public void drawArea(Relation r, Color color, MapImage fillImage, TextElement text) { 506 Multipolygon multipolygon = MultipolygonCache.getInstance().get(nc, r); 507 if (!r.isDisabled() && !multipolygon.getOuterWays().isEmpty()) { 508 for (PolyData pd : multipolygon.getCombinedPolygons()) { 509 Path2D.Double p = pd.get(); 510 if (!isAreaVisible(p)) { 511 continue; 512 } 513 drawArea(r, p, 514 pd.selected ? paintSettings.getRelationSelectedColor(color.getAlpha()) : color, 515 fillImage, text); 516 } 517 } 518 } 519 520 public void drawArea(Way w, Color color, MapImage fillImage, TextElement text) { 521 drawArea(w, getPath(w), color, fillImage, text); 522 } 523 524 public void drawBoxText(Node n, BoxTextElemStyle bs) { 525 if (!isShowNames() || bs == null) 526 return; 527 528 Point p = nc.getPoint(n); 529 TextElement text = bs.text; 530 String s = text.labelCompositionStrategy.compose(n); 531 if (s == null) return; 532 533 Font defaultFont = g.getFont(); 534 g.setFont(text.font); 535 536 int x = p.x + text.xOffset; 537 int y = p.y + text.yOffset; 538 /** 539 * 540 * left-above __center-above___ right-above 541 * left-top| |right-top 542 * | | 543 * left-center| center-center |right-center 544 * | | 545 * left-bottom|_________________|right-bottom 546 * left-below center-below right-below 547 * 548 */ 549 Rectangle box = bs.getBox(); 550 if (bs.hAlign == HorizontalTextAlignment.RIGHT) { 551 x += box.x + box.width + 2; 552 } else { 553 FontRenderContext frc = g.getFontRenderContext(); 554 Rectangle2D bounds = text.font.getStringBounds(s, frc); 555 int textWidth = (int) bounds.getWidth(); 556 if (bs.hAlign == HorizontalTextAlignment.CENTER) { 557 x -= textWidth / 2; 558 } else if (bs.hAlign == HorizontalTextAlignment.LEFT) { 559 x -= - box.x + 4 + textWidth; 560 } else throw new AssertionError(); 561 } 562 563 if (bs.vAlign == VerticalTextAlignment.BOTTOM) { 564 y += box.y + box.height; 565 } else { 566 FontRenderContext frc = g.getFontRenderContext(); 567 LineMetrics metrics = text.font.getLineMetrics(s, frc); 568 if (bs.vAlign == VerticalTextAlignment.ABOVE) { 569 y -= - box.y + metrics.getDescent(); 570 } else if (bs.vAlign == VerticalTextAlignment.TOP) { 571 y -= - box.y - metrics.getAscent(); 572 } else if (bs.vAlign == VerticalTextAlignment.CENTER) { 573 y += (metrics.getAscent() - metrics.getDescent()) / 2; 574 } else if (bs.vAlign == VerticalTextAlignment.BELOW) { 575 y += box.y + box.height + metrics.getAscent() + 2; 576 } else throw new AssertionError(); 577 } 578 if (isInactiveMode || n.isDisabled()) { 579 g.setColor(inactiveColor); 580 } else { 581 g.setColor(text.color); 582 } 583 if (text.haloRadius != null) { 584 g.setStroke(new BasicStroke(2*text.haloRadius, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 585 g.setColor(text.haloColor); 586 FontRenderContext frc = g.getFontRenderContext(); 587 GlyphVector gv = text.font.createGlyphVector(frc, s); 588 Shape textOutline = gv.getOutline(x, y); 589 g.draw(textOutline); 590 g.setStroke(new BasicStroke()); 591 g.setColor(text.color); 592 g.fill(textOutline); 593 } else { 594 g.drawString(s, x, y); 595 } 596 g.setFont(defaultFont); 597 } 598 599 public void drawLinePattern(Way way, Image pattern) { 600 final int width = pattern.getWidth(null); 601 final int height = pattern.getHeight(null); 602 603 Point lastP = null; 604 double wayLength = 0; 605 606 Iterator<Node> it = way.getNodes().iterator(); 607 while (it.hasNext()) { 608 Node n = it.next(); 609 Point thisP = nc.getPoint(n); 610 611 if (lastP != null) { 612 final double segmentLength = thisP.distance(lastP); 613 614 final double dx = thisP.x - lastP.x; 615 final double dy = thisP.y - lastP.y; 616 617 double dist = wayLength == 0 ? 0 : width - (wayLength % width); 618 619 AffineTransform saveTransform = g.getTransform(); 620 g.translate(lastP.x, lastP.y); 621 g.rotate(Math.atan2(dy, dx)); 622 623 if (dist > 0) { 624 g.drawImage(pattern, 0, 0, (int) dist, height, 625 width - (int) dist, 0, width, height, null); 626 } 627 while (dist < segmentLength) { 628 if (dist + width > segmentLength) { 629 g.drawImage(pattern, (int) dist, 0, (int) segmentLength, height, 630 0, 0, (int) segmentLength - (int) dist, height, null); 631 } else { 632 g.drawImage(pattern, (int) dist, 0, nc); 633 } 634 dist += width; 635 } 636 g.setTransform(saveTransform); 637 638 wayLength += segmentLength; 639 } 640 lastP = thisP; 641 } 642 } 643 644 @Override 645 public void drawNode(Node n, Color color, int size, boolean fill) { 646 if(size <= 0 && !n.isHighlighted()) 647 return; 648 649 Point p = nc.getPoint(n); 650 651 if(n.isHighlighted()) { 652 drawPointHighlight(p, size); 653 } 654 655 if (size > 1) { 656 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return; 657 int radius = size / 2; 658 659 if (isInactiveMode || n.isDisabled()) { 660 g.setColor(inactiveColor); 661 } else { 662 g.setColor(color); 663 } 664 if (fill) { 665 g.fillRect(p.x-radius-1, p.y-radius-1, size + 1, size + 1); 666 } else { 667 g.drawRect(p.x-radius-1, p.y-radius-1, size, size); 668 } 669 } 670 } 671 672 public void drawNodeIcon(Node n, Image img, float alpha, boolean selected, boolean member) { 673 Point p = nc.getPoint(n); 674 675 final int w = img.getWidth(null), h=img.getHeight(null); 676 if(n.isHighlighted()) { 677 drawPointHighlight(p, Math.max(w, h)); 678 } 679 680 if (alpha != 1f) { 681 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); 682 } 683 g.drawImage(img, p.x-w/2, p.y-h/2, nc); 684 g.setPaintMode(); 685 if (selected || member) 686 { 687 Color color = null; 688 if (isInactiveMode || n.isDisabled()) { 689 color = inactiveColor; 690 } else if (selected) { 691 color = selectedColor; 692 } else { 693 color = relationSelectedColor; 694 } 695 g.setColor(color); 696 g.drawRect(p.x-w/2-2, p.y-h/2-2, w+4, h+4); 697 } 698 } 699 700 public void drawNodeSymbol(Node n, Symbol s, Color fillColor, Color strokeColor) { 701 Point p = nc.getPoint(n); 702 int radius = s.size / 2; 703 704 if(n.isHighlighted()) { 705 drawPointHighlight(p, s.size); 706 } 707 708 if (fillColor != null) { 709 g.setColor(fillColor); 710 switch (s.symbol) { 711 case SQUARE: 712 g.fillRect(p.x - radius, p.y - radius, s.size, s.size); 713 break; 714 case CIRCLE: 715 g.fillOval(p.x - radius, p.y - radius, s.size, s.size); 716 break; 717 case TRIANGLE: 718 g.fillPolygon(buildPolygon(p, radius, 3, Math.PI / 2)); 719 break; 720 case PENTAGON: 721 g.fillPolygon(buildPolygon(p, radius, 5, Math.PI / 2)); 722 break; 723 case HEXAGON: 724 g.fillPolygon(buildPolygon(p, radius, 6)); 725 break; 726 case HEPTAGON: 727 g.fillPolygon(buildPolygon(p, radius, 7, Math.PI / 2)); 728 break; 729 case OCTAGON: 730 g.fillPolygon(buildPolygon(p, radius, 8, Math.PI / 8)); 731 break; 732 case NONAGON: 733 g.fillPolygon(buildPolygon(p, radius, 9, Math.PI / 2)); 734 break; 735 case DECAGON: 736 g.fillPolygon(buildPolygon(p, radius, 10)); 737 break; 738 default: 739 throw new AssertionError(); 740 } 741 } 742 if (s.stroke != null) { 743 g.setStroke(s.stroke); 744 g.setColor(strokeColor); 745 switch (s.symbol) { 746 case SQUARE: 747 g.drawRect(p.x - radius, p.y - radius, s.size - 1, s.size - 1); 748 break; 749 case CIRCLE: 750 g.drawOval(p.x - radius, p.y - radius, s.size - 1, s.size - 1); 751 break; 752 case TRIANGLE: 753 g.drawPolygon(buildPolygon(p, radius, 3, Math.PI / 2)); 754 break; 755 case PENTAGON: 756 g.drawPolygon(buildPolygon(p, radius, 5, Math.PI / 2)); 757 break; 758 case HEXAGON: 759 g.drawPolygon(buildPolygon(p, radius, 6)); 760 break; 761 case HEPTAGON: 762 g.drawPolygon(buildPolygon(p, radius, 7, Math.PI / 2)); 763 break; 764 case OCTAGON: 765 g.drawPolygon(buildPolygon(p, radius, 8, Math.PI / 8)); 766 break; 767 case NONAGON: 768 g.drawPolygon(buildPolygon(p, radius, 9, Math.PI / 2)); 769 break; 770 case DECAGON: 771 g.drawPolygon(buildPolygon(p, radius, 10)); 772 break; 773 default: 774 throw new AssertionError(); 775 } 776 g.setStroke(new BasicStroke()); 777 } 778 } 779 780 /** 781 * Draw a number of the order of the two consecutive nodes within the 782 * parents way 783 */ 784 public void drawOrderNumber(Node n1, Node n2, int orderNumber, Color clr) { 785 Point p1 = nc.getPoint(n1); 786 Point p2 = nc.getPoint(n2); 787 StyledMapRenderer.this.drawOrderNumber(p1, p2, orderNumber, clr); 788 } 789 790 /** 791 * highlights a given GeneralPath using the settings from BasicStroke to match the line's 792 * style. Width of the highlight is hard coded. 793 * @param path 794 * @param line 795 */ 796 private void drawPathHighlight(GeneralPath path, BasicStroke line) { 797 if(path == null) 798 return; 799 g.setColor(highlightColorTransparent); 800 float w = (line.getLineWidth() + 4); 801 while(w >= line.getLineWidth()) { 802 g.setStroke(new BasicStroke(w, line.getEndCap(), line.getLineJoin(), line.getMiterLimit())); 803 g.draw(path); 804 w -= 4; 805 } 806 } 807 /** 808 * highlights a given point by drawing a rounded rectangle around it. Give the 809 * size of the object you want to be highlighted, width is added automatically. 810 */ 811 private void drawPointHighlight(Point p, int size) { 812 g.setColor(highlightColorTransparent); 813 int s = size + 7; 814 while(s >= size) { 815 int r = (int) Math.floor(s/2); 816 g.fillRoundRect(p.x-r, p.y-r, s, s, r, r); 817 s -= 4; 818 } 819 } 820 821 public void drawRestriction(Image img, Point pVia, double vx, double vx2, double vy, double vy2, double angle, boolean selected) { 822 /* rotate image with direction last node in from to */ 823 Image rotatedImg = ImageProvider.createRotatedImage(null , img, angle); 824 825 /* scale down image to 16*16 pixels */ 826 Image smallImg = new ImageIcon(rotatedImg.getScaledInstance(16 , 16, Image.SCALE_SMOOTH)).getImage(); 827 int w = smallImg.getWidth(null), h=smallImg.getHeight(null); 828 g.drawImage(smallImg, (int)(pVia.x+vx+vx2)-w/2, (int)(pVia.y+vy+vy2)-h/2, nc); 829 830 if (selected) { 831 g.setColor(isInactiveMode ? inactiveColor : relationSelectedColor); 832 g.drawRect((int)(pVia.x+vx+vx2)-w/2-2,(int)(pVia.y+vy+vy2)-h/2-2, w+4, h+4); 833 } 834 } 835 836 public void drawRestriction(Relation r, MapImage icon) { 837 Way fromWay = null; 838 Way toWay = null; 839 OsmPrimitive via = null; 840 841 /* find the "from", "via" and "to" elements */ 842 for (RelationMember m : r.getMembers()) 843 { 844 if(m.getMember().isIncomplete()) 845 return; 846 else 847 { 848 if(m.isWay()) 849 { 850 Way w = m.getWay(); 851 if(w.getNodesCount() < 2) { 852 continue; 853 } 854 855 if("from".equals(m.getRole())) { 856 if(fromWay == null) { 857 fromWay = w; 858 } 859 } else if("to".equals(m.getRole())) { 860 if(toWay == null) { 861 toWay = w; 862 } 863 } else if("via".equals(m.getRole())) { 864 if(via == null) { 865 via = w; 866 } 867 } 868 } 869 else if(m.isNode()) 870 { 871 Node n = m.getNode(); 872 if("via".equals(m.getRole()) && via == null) { 873 via = n; 874 } 875 } 876 } 877 } 878 879 if (fromWay == null || toWay == null || via == null) 880 return; 881 882 Node viaNode; 883 if(via instanceof Node) 884 { 885 viaNode = (Node) via; 886 if(!fromWay.isFirstLastNode(viaNode)) 887 return; 888 } 889 else 890 { 891 Way viaWay = (Way) via; 892 Node firstNode = viaWay.firstNode(); 893 Node lastNode = viaWay.lastNode(); 894 Boolean onewayvia = false; 895 896 String onewayviastr = viaWay.get("oneway"); 897 if(onewayviastr != null) 898 { 899 if("-1".equals(onewayviastr)) { 900 onewayvia = true; 901 Node tmp = firstNode; 902 firstNode = lastNode; 903 lastNode = tmp; 904 } else { 905 onewayvia = OsmUtils.getOsmBoolean(onewayviastr); 906 if (onewayvia == null) { 907 onewayvia = false; 908 } 909 } 910 } 911 912 if(fromWay.isFirstLastNode(firstNode)) { 913 viaNode = firstNode; 914 } else if (!onewayvia && fromWay.isFirstLastNode(lastNode)) { 915 viaNode = lastNode; 916 } else 917 return; 918 } 919 920 /* find the "direct" nodes before the via node */ 921 Node fromNode = null; 922 if(fromWay.firstNode() == via) { 923 fromNode = fromWay.getNode(1); 924 } else { 925 fromNode = fromWay.getNode(fromWay.getNodesCount()-2); 926 } 927 928 Point pFrom = nc.getPoint(fromNode); 929 Point pVia = nc.getPoint(viaNode); 930 931 /* starting from via, go back the "from" way a few pixels 932 (calculate the vector vx/vy with the specified length and the direction 933 away from the "via" node along the first segment of the "from" way) 934 */ 935 double distanceFromVia=14; 936 double dx = (pFrom.x >= pVia.x) ? (pFrom.x - pVia.x) : (pVia.x - pFrom.x); 937 double dy = (pFrom.y >= pVia.y) ? (pFrom.y - pVia.y) : (pVia.y - pFrom.y); 938 939 double fromAngle; 940 if(dx == 0.0) { 941 fromAngle = Math.PI/2; 942 } else { 943 fromAngle = Math.atan(dy / dx); 944 } 945 double fromAngleDeg = Math.toDegrees(fromAngle); 946 947 double vx = distanceFromVia * Math.cos(fromAngle); 948 double vy = distanceFromVia * Math.sin(fromAngle); 949 950 if(pFrom.x < pVia.x) { 951 vx = -vx; 952 } 953 if(pFrom.y < pVia.y) { 954 vy = -vy; 955 } 956 957 /* go a few pixels away from the way (in a right angle) 958 (calculate the vx2/vy2 vector with the specified length and the direction 959 90degrees away from the first segment of the "from" way) 960 */ 961 double distanceFromWay=10; 962 double vx2 = 0; 963 double vy2 = 0; 964 double iconAngle = 0; 965 966 if(pFrom.x >= pVia.x && pFrom.y >= pVia.y) { 967 if(!leftHandTraffic) { 968 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90)); 969 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90)); 970 } else { 971 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90)); 972 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90)); 973 } 974 iconAngle = 270+fromAngleDeg; 975 } 976 if(pFrom.x < pVia.x && pFrom.y >= pVia.y) { 977 if(!leftHandTraffic) { 978 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg)); 979 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg)); 980 } else { 981 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180)); 982 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180)); 983 } 984 iconAngle = 90-fromAngleDeg; 985 } 986 if(pFrom.x < pVia.x && pFrom.y < pVia.y) { 987 if(!leftHandTraffic) { 988 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90)); 989 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90)); 990 } else { 991 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90)); 992 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90)); 993 } 994 iconAngle = 90+fromAngleDeg; 995 } 996 if(pFrom.x >= pVia.x && pFrom.y < pVia.y) { 997 if(!leftHandTraffic) { 998 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180)); 999 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180)); 1000 } else { 1001 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg)); 1002 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg)); 1003 } 1004 iconAngle = 270-fromAngleDeg; 1005 } 1006 1007 drawRestriction(isInactiveMode || r.isDisabled() ? icon.getDisabled() : icon.getImage(), 1008 pVia, vx, vx2, vy, vy2, iconAngle, r.isSelected()); 1009 } 1010 1011 public void drawTextOnPath(Way way, TextElement text) { 1012 if (way == null || text == null) 1013 return; 1014 String name = text.getString(way); 1015 if (name == null || name.isEmpty()) 1016 return; 1017 1018 Polygon poly = new Polygon(); 1019 Point lastPoint = null; 1020 Iterator<Node> it = way.getNodes().iterator(); 1021 double pathLength = 0; 1022 long dx, dy; 1023 while (it.hasNext()) { 1024 Node n = it.next(); 1025 Point p = nc.getPoint(n); 1026 poly.addPoint(p.x, p.y); 1027 1028 if(lastPoint != null) { 1029 dx = p.x - lastPoint.x; 1030 dy = p.y - lastPoint.y; 1031 pathLength += Math.sqrt(dx*dx + dy*dy); 1032 } 1033 lastPoint = p; 1034 } 1035 1036 FontMetrics fontMetrics = g.getFontMetrics(text.font); // if slow, use cache 1037 Rectangle2D rec = fontMetrics.getStringBounds(name, g); // if slow, approximate by strlen()*maxcharbounds(font) 1038 1039 if (rec.getWidth() > pathLength) 1040 return; 1041 1042 double t1 = (pathLength/2 - rec.getWidth()/2) / pathLength; 1043 double t2 = (pathLength/2 + rec.getWidth()/2) / pathLength; 1044 1045 double[] p1 = pointAt(t1, poly, pathLength); 1046 double[] p2 = pointAt(t2, poly, pathLength); 1047 1048 if (p1 == null || p2 == null) 1049 return; 1050 1051 double angleOffset; 1052 double offsetSign; 1053 double tStart; 1054 1055 if (p1[0] < p2[0] && 1056 p1[2] < Math.PI/2 && 1057 p1[2] > -Math.PI/2) { 1058 angleOffset = 0; 1059 offsetSign = 1; 1060 tStart = t1; 1061 } else { 1062 angleOffset = Math.PI; 1063 offsetSign = -1; 1064 tStart = t2; 1065 } 1066 1067 FontRenderContext frc = g.getFontRenderContext(); 1068 GlyphVector gv = text.font.createGlyphVector(frc, name); 1069 1070 for (int i=0; i<gv.getNumGlyphs(); ++i) { 1071 Rectangle2D rect = gv.getGlyphLogicalBounds(i).getBounds2D(); 1072 double t = tStart + offsetSign * (rect.getX() + rect.getWidth()/2) / pathLength; 1073 double[] p = pointAt(t, poly, pathLength); 1074 if (p != null) { 1075 AffineTransform trfm = AffineTransform.getTranslateInstance(p[0] - rect.getX(), p[1]); 1076 trfm.rotate(p[2]+angleOffset); 1077 double off = -rect.getY() - rect.getHeight()/2 + text.yOffset; 1078 trfm.translate(-rect.getWidth()/2, off); 1079 if (isGlyphVectorDoubleTranslationBug()) { 1080 // scale the translation components by one half 1081 AffineTransform tmp = AffineTransform.getTranslateInstance(-0.5 * trfm.getTranslateX(), -0.5 * trfm.getTranslateY()); 1082 tmp.concatenate(trfm); 1083 trfm = tmp; 1084 } 1085 gv.setGlyphTransform(i, trfm); 1086 } 1087 } 1088 if (text.haloRadius != null) { 1089 Shape textOutline = gv.getOutline(); 1090 g.setStroke(new BasicStroke(2*text.haloRadius, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 1091 g.setColor(text.haloColor); 1092 g.draw(textOutline); 1093 g.setStroke(new BasicStroke()); 1094 g.setColor(text.color); 1095 g.fill(textOutline); 1096 } else { 1097 g.setColor(text.color); 1098 g.drawGlyphVector(gv, 0, 0); 1099 } 1100 } 1101 1102 /** 1103 * draw way 1104 * @param showOrientation show arrows that indicate the technical orientation of 1105 * the way (defined by order of nodes) 1106 * @param showOneway show symbols that indicate the direction of the feature, 1107 * e.g. oneway street or waterway 1108 * @param onewayReversed for oneway=-1 and similar 1109 */ 1110 public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor, float offset, 1111 boolean showOrientation, boolean showHeadArrowOnly, 1112 boolean showOneway, boolean onewayReversed) { 1113 1114 GeneralPath path = new GeneralPath(); 1115 GeneralPath orientationArrows = showOrientation ? new GeneralPath() : null; 1116 GeneralPath onewayArrows = showOneway ? new GeneralPath() : null; 1117 GeneralPath onewayArrowsCasing = showOneway ? new GeneralPath() : null; 1118 Rectangle bounds = g.getClipBounds(); 1119 bounds.grow(100, 100); // avoid arrow heads at the border 1120 1121 double wayLength = 0; 1122 Point lastPoint = null; 1123 boolean initialMoveToNeeded = true; 1124 List<Node> wayNodes = way.getNodes(); 1125 if (wayNodes.size() < 2) return; 1126 1127 // only highlight the segment if the way itself is not highlighted 1128 if (!way.isHighlighted()) { 1129 GeneralPath highlightSegs = null; 1130 for (WaySegment ws : highlightWaySegments) { 1131 if (ws.way != way || ws.lowerIndex < offset) { 1132 continue; 1133 } 1134 if(highlightSegs == null) { 1135 highlightSegs = new GeneralPath(); 1136 } 1137 1138 Point p1 = nc.getPoint(ws.getFirstNode()); 1139 Point p2 = nc.getPoint(ws.getSecondNode()); 1140 highlightSegs.moveTo(p1.x, p1.y); 1141 highlightSegs.lineTo(p2.x, p2.y); 1142 } 1143 1144 drawPathHighlight(highlightSegs, line); 1145 } 1146 1147 Iterator<Point> it = new OffsetIterator(wayNodes, offset); 1148 while (it.hasNext()) { 1149 Point p = it.next(); 1150 if (lastPoint != null) { 1151 Point p1 = lastPoint; 1152 Point p2 = p; 1153 1154 /** 1155 * Do custom clipping to work around openjdk bug. It leads to 1156 * drawing artefacts when zooming in a lot. (#4289, #4424) 1157 * (Looks like int overflow.) 1158 */ 1159 LineClip clip = new LineClip(p1, p2, bounds); 1160 if (clip.execute()) { 1161 if (!p1.equals(clip.getP1())) { 1162 p1 = clip.getP1(); 1163 path.moveTo(p1.x, p1.y); 1164 } else if (initialMoveToNeeded) { 1165 initialMoveToNeeded = false; 1166 path.moveTo(p1.x, p1.y); 1167 } 1168 p2 = clip.getP2(); 1169 path.lineTo(p2.x, p2.y); 1170 1171 /* draw arrow */ 1172 if (showHeadArrowOnly ? !it.hasNext() : showOrientation) { 1173 final double segmentLength = p1.distance(p2); 1174 if (segmentLength != 0.0) { 1175 final double l = (10. + line.getLineWidth()) / segmentLength; 1176 1177 final double sx = l * (p1.x - p2.x); 1178 final double sy = l * (p1.y - p2.y); 1179 1180 orientationArrows.moveTo (p2.x + cosPHI * sx - sinPHI * sy, p2.y + sinPHI * sx + cosPHI * sy); 1181 orientationArrows.lineTo(p2.x, p2.y); 1182 orientationArrows.lineTo (p2.x + cosPHI * sx + sinPHI * sy, p2.y - sinPHI * sx + cosPHI * sy); 1183 } 1184 } 1185 if (showOneway) { 1186 final double segmentLength = p1.distance(p2); 1187 if (segmentLength != 0.0) { 1188 final double nx = (p2.x - p1.x) / segmentLength; 1189 final double ny = (p2.y - p1.y) / segmentLength; 1190 1191 final double interval = 60; 1192 // distance from p1 1193 double dist = interval - (wayLength % interval); 1194 1195 while (dist < segmentLength) { 1196 for (Pair<Float, GeneralPath> sizeAndPath : Arrays.asList(new Pair[] { 1197 new Pair<Float, GeneralPath>(3f, onewayArrowsCasing), 1198 new Pair<Float, GeneralPath>(2f, onewayArrows)})) { 1199 1200 // scale such that border is 1 px 1201 final double fac = - (onewayReversed ? -1 : 1) * sizeAndPath.a * (1 + sinPHI) / (sinPHI * cosPHI); 1202 final double sx = nx * fac; 1203 final double sy = ny * fac; 1204 1205 // Attach the triangle at the incenter and not at the tip. 1206 // Makes the border even at all sides. 1207 final double x = p1.x + nx * (dist + (onewayReversed ? -1 : 1) * (sizeAndPath.a / sinPHI)); 1208 final double y = p1.y + ny * (dist + (onewayReversed ? -1 : 1) * (sizeAndPath.a / sinPHI)); 1209 1210 sizeAndPath.b.moveTo(x, y); 1211 sizeAndPath.b.lineTo (x + cosPHI * sx - sinPHI * sy, y + sinPHI * sx + cosPHI * sy); 1212 sizeAndPath.b.lineTo (x + cosPHI * sx + sinPHI * sy, y - sinPHI * sx + cosPHI * sy); 1213 sizeAndPath.b.lineTo(x, y); 1214 } 1215 dist += interval; 1216 } 1217 } 1218 wayLength += segmentLength; 1219 } 1220 } 1221 } 1222 lastPoint = p; 1223 } 1224 if(way.isHighlighted()) { 1225 drawPathHighlight(path, line); 1226 } 1227 displaySegments(path, orientationArrows, onewayArrows, onewayArrowsCasing, color, line, dashes, dashedColor); 1228 } 1229 1230 public double getCircum() { 1231 return circum; 1232 } 1233 1234 @Override 1235 public void getColors() { 1236 super.getColors(); 1237 this.relationSelectedColor = PaintColors.RELATIONSELECTED.get(); 1238 this.highlightColorTransparent = new Color(highlightColor.getRed(), highlightColor.getGreen(), highlightColor.getBlue(), 100); 1239 this.backgroundColor = PaintColors.getBackgroundColor(); 1240 } 1241 1242 @Override 1243 protected void getSettings(boolean virtual) { 1244 super.getSettings(virtual); 1245 paintSettings = MapPaintSettings.INSTANCE; 1246 1247 circum = nc.getDist100Pixel(); 1248 1249 leftHandTraffic = Main.pref.getBoolean("mappaint.lefthandtraffic", false); 1250 1251 useStrokes = paintSettings.getUseStrokesDistance() > circum; 1252 showNames = paintSettings.getShowNamesDistance() > circum; 1253 showIcons = paintSettings.getShowIconsDistance() > circum; 1254 isOutlineOnly = paintSettings.isOutlineOnly(); 1255 orderFont = new Font(Main.pref.get("mappaint.font", "Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8)); 1256 1257 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 1258 Main.pref.getBoolean("mappaint.use-antialiasing", true) ? 1259 RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); 1260 } 1261 1262 private Path2D.Double getPath(Way w) { 1263 Path2D.Double path = new Path2D.Double(); 1264 boolean initial = true; 1265 for (Node n : w.getNodes()) { 1266 Point2D p = n.getEastNorth(); 1267 if (p != null) { 1268 if (initial) { 1269 path.moveTo(p.getX(), p.getY()); 1270 initial = false; 1271 } else { 1272 path.lineTo(p.getX(), p.getY()); 1273 } 1274 } 1275 } 1276 return path; 1277 } 1278 1279 private boolean isAreaVisible(Path2D.Double area) { 1280 Rectangle2D bounds = area.getBounds2D(); 1281 if (bounds.isEmpty()) return false; 1282 Point2D p = nc.getPoint2D(new EastNorth(bounds.getX(), bounds.getY())); 1283 if (p.getX() > nc.getWidth()) return false; 1284 if (p.getY() < 0) return false; 1285 p = nc.getPoint2D(new EastNorth(bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight())); 1286 if (p.getX() < 0) return false; 1287 if (p.getY() > nc.getHeight()) return false; 1288 return true; 1289 } 1290 1291 public boolean isInactiveMode() { 1292 return isInactiveMode; 1293 } 1294 1295 public boolean isShowIcons() { 1296 return showIcons; 1297 } 1298 1299 public boolean isShowNames() { 1300 return showNames; 1301 } 1302 1303 private double[] pointAt(double t, Polygon poly, double pathLength) { 1304 double totalLen = t * pathLength; 1305 double curLen = 0; 1306 long dx, dy; 1307 double segLen; 1308 1309 // Yes, it is inefficient to iterate from the beginning for each glyph. 1310 // Can be optimized if it turns out to be slow. 1311 for (int i = 1; i < poly.npoints; ++i) { 1312 dx = poly.xpoints[i] - poly.xpoints[i-1]; 1313 dy = poly.ypoints[i] - poly.ypoints[i-1]; 1314 segLen = Math.sqrt(dx*dx + dy*dy); 1315 if (totalLen > curLen + segLen) { 1316 curLen += segLen; 1317 continue; 1318 } 1319 return new double[] { 1320 poly.xpoints[i-1]+(totalLen - curLen)/segLen*dx, 1321 poly.ypoints[i-1]+(totalLen - curLen)/segLen*dy, 1322 Math.atan2(dy, dx)}; 1323 } 1324 return null; 201 1325 } 202 1326 … … 205 1329 //long start = System.currentTimeMillis(); 206 1330 BBox bbox = new BBox(bounds); 207 208 styles = MapPaintStyles.getStyles(); 209 210 this.paintSettings = MapPaintSettings.INSTANCE; 211 212 circum = nc.getDist100Pixel(); 1331 getSettings(renderVirtualNodes); 1332 213 1333 boolean drawArea = circum <= Main.pref.getInteger("mappaint.fillareas", 10000000); 214 1334 boolean drawMultipolygon = drawArea && Main.pref.getBoolean("mappaint.multipolygon", true); 1335 boolean drawRestriction = Main.pref.getBoolean("mappaint.restriction", true); 1336 1337 styles = MapPaintStyles.getStyles(); 215 1338 styles.setDrawMultipolygon(drawMultipolygon); 216 boolean drawRestriction = Main.pref.getBoolean("mappaint.restriction", true); 217 boolean leftHandTraffic = Main.pref.getBoolean("mappaint.lefthandtraffic", false); 218 219 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 220 Main.pref.getBoolean("mappaint.use-antialiasing", true) ? 221 RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); 222 223 Collection<WaySegment> hws = data.getHighlightedWaySegments(); 224 225 this.painter = new MapPainter(paintSettings, g, isInactiveMode, nc, renderVirtualNodes, circum, leftHandTraffic, hws); 1339 1340 highlightWaySegments = data.getHighlightedWaySegments(); 226 1341 227 1342 StyleCollector sc = new StyleCollector(drawArea, drawMultipolygon, drawRestriction); … … 232 1347 sc.drawAll(); 233 1348 sc = null; 234 painter.drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes());1349 drawVirtualNodes(data, bbox); 235 1350 236 1351 //long now = System.currentTimeMillis(); -
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java
r5421 r5571 11 11 import java.awt.Stroke; 12 12 import java.awt.geom.GeneralPath; 13 import java.awt.geom.Point2D;14 import java.util.Collection;15 13 import java.util.Iterator; 16 14 … … 35 33 public class WireframeMapRenderer extends AbstractMapRenderer implements Visitor { 36 34 37 /** Color Preference for inactive objects */38 protected Color inactiveColor;39 /** Color Preference for selected objects */40 protected Color selectedColor;41 /** Color Preference for nodes */42 protected Color nodeColor;43 35 /** Color Preference for ways not matching any other group */ 44 36 protected Color dfltWayColor; … … 47 39 /** Color Preference for untagged ways */ 48 40 protected Color untaggedWayColor; 49 /** Color Preference for background */50 protected Color backgroundColor;51 /** Color Preference for hightlighted objects */52 protected Color highlightColor;53 41 /** Color Preference for tagged nodes */ 54 42 protected Color taggedColor; … … 81 69 /** Preference: size of tagged nodes */ 82 70 protected int taggedNodeSize; 83 /** Preference: size of virtual nodes (0 displayes display) */84 protected int virtualNodeSize;85 /** Preference: minimum space (displayed way length) to display virtual nodes */86 protected int virtualNodeSpace;87 /** Preference: minimum space (displayed way length) to display segment numbers */88 protected int segmentNumberSpace;89 71 90 72 /** Color cache to draw subsequent segments of same color as one <code>Path</code>. */ … … 123 105 } 124 106 125 /** 126 * Reads the color definitions from preferences. This function is <code>public</code>, so that 127 * color names in preferences can be displayed even without calling the wireframe display before. 128 */ 129 public void getColors() 130 { 131 inactiveColor = PaintColors.INACTIVE.get(); 132 selectedColor = PaintColors.SELECTED.get(); 133 nodeColor = PaintColors.NODE.get(); 107 @Override 108 public void getColors() { 109 super.getColors(); 134 110 dfltWayColor = PaintColors.DEFAULT_WAY.get(); 135 111 relationColor = PaintColors.RELATION.get(); 136 112 untaggedWayColor = PaintColors.UNTAGGED_WAY.get(); 137 backgroundColor = PaintColors.BACKGROUND.get();138 113 highlightColor = PaintColors.HIGHLIGHT_WIREFRAME.get(); 139 114 taggedColor = PaintColors.TAGGED.get(); … … 147 122 } 148 123 149 /** 150 * Reads all the settings from preferences. Calls the @{link #getColors} 151 * function. 152 * 153 * @param virtual <code>true</code> if virtual nodes are used 154 */ 124 @Override 155 125 protected void getSettings(boolean virtual) { 126 super.getSettings(virtual); 156 127 MapPaintSettings settings = MapPaintSettings.INSTANCE; 157 128 showDirectionArrow = settings.isShowDirectionArrow(); … … 167 138 fillConnectionNode = settings.isFillConnectionNode(); 168 139 fillTaggedNode = settings.isFillTaggedNode(); 169 virtualNodeSize = virtual ? Main.pref.getInteger("mappaint.node.virtual-size", 8) / 2 : 0;170 virtualNodeSpace = Main.pref.getInteger("mappaint.node.virtual-space", 70);171 segmentNumberSpace = Main.pref.getInteger("mappaint.segmentnumber.space", 40);172 getColors();173 140 174 141 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, … … 224 191 } 225 192 } 226 drawVirtualNodes(data .searchWays(bbox), data.getHighlightedVirtualNodes());193 drawVirtualNodes(data, bbox); 227 194 228 195 // draw highlighted way segments over the already drawn ways. Otherwise each … … 230 197 // in most of the cases there won't be more than one segment. Since the wireframe 231 198 // renderer does not feature any transparency there should be no visual difference. 232 for (final WaySegment wseg : data.getHighlightedWaySegments()) {199 for (final WaySegment wseg : data.getHighlightedWaySegments()) { 233 200 drawSegment(nc.getPoint(wseg.getFirstNode()), nc.getPoint(wseg.getSecondNode()), highlightColor, false); 234 201 } … … 296 263 297 264 /** 298 * Checks if a way segemnt is large enough for additional information display.299 *300 * @param p1 First point of the way segment.301 * @param p2 Second point of the way segment.302 * @param space The free space to check against.303 * @return <code>true</code> if segment is larger than required space304 */305 public static boolean isLargeSegment(Point2D p1, Point2D p2, int space)306 {307 double xd = Math.abs(p1.getX()-p2.getX());308 double yd = Math.abs(p1.getY()-p2.getY());309 return (xd+yd > space);310 }311 312 /**313 * Draws virtual nodes.314 *315 * @param ways The ways to draw nodes for.316 * @param highlightVirtualNodes Way segements, where nodesshould be highlighted.317 */318 public void drawVirtualNodes(Collection<Way> ways, Collection<WaySegment> highlightVirtualNodes) {319 if (virtualNodeSize == 0)320 return;321 // print normal virtual nodes322 GeneralPath path = new GeneralPath();323 for (Way osm : ways) {324 if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) {325 visitVirtual(path, osm);326 }327 }328 g.setColor(nodeColor);329 g.draw(path);330 // print highlighted virtual nodes. Since only the color changes, simply331 // drawing them over the existing ones works fine (at least in their current332 // simple style)333 path = new GeneralPath();334 for (WaySegment wseg: highlightVirtualNodes){335 if (wseg.way.isUsable() && !wseg.way.isDisabled()) {336 visitVirtual(path, wseg.toWay());337 }338 }339 g.setColor(highlightColor);340 g.draw(path);341 }342 343 /**344 * Creates path for drawing virtual nodes for one way.345 *346 * @param path The path to append drawing to.347 * @param w The ways to draw node for.348 */349 public void visitVirtual(GeneralPath path, Way w) {350 Iterator<Node> it = w.getNodes().iterator();351 if (it.hasNext()) {352 Point lastP = nc.getPoint(it.next());353 while(it.hasNext())354 {355 Point p = nc.getPoint(it.next());356 if(isSegmentVisible(lastP, p) && isLargeSegment(lastP, p, virtualNodeSpace))357 {358 int x = (p.x+lastP.x)/2;359 int y = (p.y+lastP.y)/2;360 path.moveTo(x-virtualNodeSize, y);361 path.lineTo(x+virtualNodeSize, y);362 path.moveTo(x, y-virtualNodeSize);363 path.lineTo(x, y+virtualNodeSize);364 }365 lastP = p;366 }367 }368 }369 370 /**371 265 * Draw a line for all way segments. 372 266 * @param w The way to draw. … … 406 300 showOnlyHeadArrowOnly ? !it.hasNext() : showThisDirectionArrow); 407 301 if (showOrderNumber && !isInactiveMode) { 408 drawOrderNumber(lastP, p, orderNumber );302 drawOrderNumber(lastP, p, orderNumber, g.getColor()); 409 303 } 410 304 lastP = p; … … 473 367 public void visit(Changeset cs) {/* ignore */} 474 368 475 /** 476 * Draw an number of the order of the two consecutive nodes within the 477 * parents way 478 * 479 * @param p1 First point of the way segment. 480 * @param p2 Second point of the way segment. 481 * @param orderNumber The number of the segment in the way. 482 */ 483 protected void drawOrderNumber(Point p1, Point p2, int orderNumber) { 484 if (isSegmentVisible(p1, p2) && isLargeSegment(p1, p2, segmentNumberSpace)) { 485 String on = Integer.toString(orderNumber); 486 int strlen = on.length(); 487 int x = (p1.x+p2.x)/2 - 4*strlen; 488 int y = (p1.y+p2.y)/2 + 4; 489 490 if(virtualNodeSize != 0 && isLargeSegment(p1, p2, virtualNodeSpace)) 491 { 492 y = (p1.y+p2.y)/2 - virtualNodeSize - 3; 493 } 494 495 displaySegments(); /* draw nodes on top! */ 496 Color c = g.getColor(); 497 g.setColor(backgroundColor); 498 g.fillRect(x-1, y-12, 8*strlen+1, 14); 499 g.setColor(c); 500 g.drawString(on, x, y); 501 } 502 } 503 504 /** 505 * Draw the node as small rectangle with the given color. 506 * 507 * @param n The node to draw. 508 * @param color The color of the node. 509 */ 369 @Override 510 370 public void drawNode(Node n, Color color, int size, boolean fill) { 511 371 if (size > 1) { … … 572 432 573 433 /** 574 * Checks if segment is visible in display.575 *576 * @param p1 First point of the way segment.577 * @param p2 Second point of the way segment.578 * @return <code>true</code> if segment is visible.579 */580 protected boolean isSegmentVisible(Point p1, Point p2) {581 if ((p1.x < 0) && (p2.x < 0)) return false;582 if ((p1.y < 0) && (p2.y < 0)) return false;583 if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false;584 if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false;585 return true;586 }587 588 /**589 434 * Checks if a polygon is visible in display. 590 435 * -
trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java
r5376 r5571 11 11 import org.openstreetmap.josm.data.osm.Way; 12 12 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; 13 import org.openstreetmap.josm.data.osm.visitor.paint. MapPainter;13 import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer; 14 14 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; 15 15 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference; … … 78 78 79 79 @Override 80 public void paintPrimitive(OsmPrimitive osm, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member) {80 public void paintPrimitive(OsmPrimitive osm, MapPaintSettings paintSettings, StyledMapRenderer painter, boolean selected, boolean member) { 81 81 if (osm instanceof Way) 82 82 { -
trunk/src/org/openstreetmap/josm/gui/mappaint/BoxTextElemStyle.java
r5342 r5571 10 10 import org.openstreetmap.josm.data.osm.OsmPrimitive; 11 11 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; 12 import org.openstreetmap.josm.data.osm.visitor.paint. MapPainter;12 import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer; 13 13 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; 14 14 import org.openstreetmap.josm.tools.CheckParameterUtil; … … 181 181 182 182 @Override 183 public void paintPrimitive(OsmPrimitive osm, MapPaintSettings settings, MapPainter painter, boolean selected, boolean member) {183 public void paintPrimitive(OsmPrimitive osm, MapPaintSettings settings, StyledMapRenderer painter, boolean selected, boolean member) { 184 184 if (osm instanceof Node) { 185 185 painter.drawBoxText((Node) osm, this); -
trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java
r5342 r5571 11 11 import org.openstreetmap.josm.data.osm.OsmPrimitive; 12 12 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; 13 import org.openstreetmap.josm.data.osm.visitor.paint. MapPainter;13 import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer; 14 14 import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat; 15 15 … … 44 44 * @param member true, if primitive is not selected and member of a selected relation 45 45 */ 46 public abstract void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member);46 public abstract void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter, boolean selected, boolean member); 47 47 48 48 public boolean isProperLineStyle() { -
trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
r5342 r5571 12 12 import org.openstreetmap.josm.data.osm.Way; 13 13 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; 14 import org.openstreetmap.josm.data.osm.visitor.paint. MapPainter;14 import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer; 15 15 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; 16 16 import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat; … … 266 266 267 267 @Override 268 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member) {268 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter, boolean selected, boolean member) { 269 269 Way w = (Way)primitive; 270 270 /* show direction arrows, if draw.segment.relevant_directions_only is not set, -
trunk/src/org/openstreetmap/josm/gui/mappaint/LinePatternElemStyle.java
r5217 r5571 5 5 import org.openstreetmap.josm.data.osm.Way; 6 6 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; 7 import org.openstreetmap.josm.data.osm.visitor.paint. MapPainter;7 import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer; 8 8 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference; 9 9 … … 31 31 32 32 @Override 33 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member) {33 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter, boolean selected, boolean member) { 34 34 Way w = (Way)primitive; 35 35 painter.drawLinePattern(w, pattern.getImage()); -
trunk/src/org/openstreetmap/josm/gui/mappaint/LineTextElemStyle.java
r5342 r5571 5 5 import org.openstreetmap.josm.data.osm.Way; 6 6 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; 7 import org.openstreetmap.josm.data.osm.visitor.paint. MapPainter;7 import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer; 8 8 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; 9 9 import org.openstreetmap.josm.tools.Utils; … … 31 31 32 32 @Override 33 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member) {33 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter, boolean selected, boolean member) { 34 34 Way w = (Way)primitive; 35 35 painter.drawTextOnPath(w, text); -
trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
r5342 r5571 14 14 import org.openstreetmap.josm.data.osm.Relation; 15 15 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings; 16 import org.openstreetmap.josm.data.osm.visitor.paint. MapPainter;16 import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer; 17 17 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.BoxProvider; 18 18 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.SimpleBoxProvider; … … 230 230 231 231 @Override 232 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings settings, MapPainter painter, boolean selected, boolean member) {232 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings settings, StyledMapRenderer painter, boolean selected, boolean member) { 233 233 if (primitive instanceof Node) { 234 234 Node n = (Node) primitive;
Note:
See TracChangeset
for help on using the changeset viewer.