source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/AbstractMapRenderer.java@ 12620

Last change on this file since 12620 was 12620, checked in by Don-vip, 7 years ago

see #15182 - deprecate all Main logging methods and introduce suitable replacements in Logging for most of them

  • Property svn:eol-style set to native
File size: 9.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm.visitor.paint;
3
4import java.awt.Color;
5import java.awt.Graphics2D;
6import java.awt.geom.GeneralPath;
7import java.awt.geom.Path2D;
8import java.awt.geom.Rectangle2D;
9import java.util.Iterator;
10
11import org.openstreetmap.josm.Main;
12import org.openstreetmap.josm.data.osm.BBox;
13import org.openstreetmap.josm.data.osm.DataSet;
14import org.openstreetmap.josm.data.osm.Node;
15import org.openstreetmap.josm.data.osm.Way;
16import org.openstreetmap.josm.data.osm.WaySegment;
17import org.openstreetmap.josm.gui.MapViewState;
18import org.openstreetmap.josm.gui.MapViewState.MapViewPoint;
19import org.openstreetmap.josm.gui.MapViewState.MapViewRectangle;
20import org.openstreetmap.josm.gui.NavigatableComponent;
21import org.openstreetmap.josm.tools.CheckParameterUtil;
22import org.openstreetmap.josm.tools.Logging;
23
24/**
25 * <p>Abstract common superclass for {@link Rendering} implementations.</p>
26 * @since 4087
27 */
28public abstract class AbstractMapRenderer implements Rendering {
29
30 /** the graphics context to which the visitor renders OSM objects */
31 protected final Graphics2D g;
32 /** the map viewport - provides projection and hit detection functionality */
33 protected final NavigatableComponent nc;
34
35 /**
36 * The {@link MapViewState} to use to convert between coordinates.
37 */
38 protected final MapViewState mapState;
39
40 /** if true, the paint visitor shall render OSM objects such that they
41 * look inactive. Example: rendering of data in an inactive layer using light gray as color only. */
42 protected boolean isInactiveMode;
43 /** Color Preference for background */
44 protected Color backgroundColor;
45 /** Color Preference for inactive objects */
46 protected Color inactiveColor;
47 /** Color Preference for selected objects */
48 protected Color selectedColor;
49 /** Color Preference for members of selected relations */
50 protected Color relationSelectedColor;
51 /** Color Preference for nodes */
52 protected Color nodeColor;
53
54 /** Color Preference for hightlighted objects */
55 protected Color highlightColor;
56 /** Preference: size of virtual nodes (0 displayes display) */
57 protected int virtualNodeSize;
58 /** Preference: minimum space (displayed way length) to display virtual nodes */
59 protected int virtualNodeSpace;
60
61 /** Preference: minimum space (displayed way length) to display segment numbers */
62 protected int segmentNumberSpace;
63
64 /**
65 * <p>Creates an abstract paint visitor</p>
66 *
67 * @param g the graphics context. Must not be null.
68 * @param nc the map viewport. Must not be null.
69 * @param isInactiveMode if true, the paint visitor shall render OSM objects such that they
70 * look inactive. Example: rendering of data in an inactive layer using light gray as color only.
71 * @throws IllegalArgumentException if {@code g} is null
72 * @throws IllegalArgumentException if {@code nc} is null
73 */
74 public AbstractMapRenderer(Graphics2D g, NavigatableComponent nc, boolean isInactiveMode) {
75 CheckParameterUtil.ensureParameterNotNull(g);
76 CheckParameterUtil.ensureParameterNotNull(nc);
77 this.g = g;
78 this.nc = nc;
79 this.mapState = nc.getState();
80 this.isInactiveMode = isInactiveMode;
81 }
82
83 /**
84 * Draw the node as small square with the given color.
85 *
86 * @param n The node to draw.
87 * @param color The color of the node.
88 * @param size size in pixels
89 * @param fill determines if the square mmust be filled
90 */
91 public abstract void drawNode(Node n, Color color, int size, boolean fill);
92
93 /**
94 * Draw an number of the order of the two consecutive nodes within the
95 * parents way
96 *
97 * @param p1 First point of the way segment.
98 * @param p2 Second point of the way segment.
99 * @param orderNumber The number of the segment in the way.
100 * @param clr The color to use for drawing the text.
101 * @since 10827
102 */
103 protected void drawOrderNumber(MapViewPoint p1, MapViewPoint p2, int orderNumber, Color clr) {
104 if (isSegmentVisible(p1, p2) && isLargeSegment(p1, p2, segmentNumberSpace)) {
105 String on = Integer.toString(orderNumber);
106 int strlen = on.length();
107 double centerX = (p1.getInViewX()+p2.getInViewX())/2;
108 double centerY = (p1.getInViewY()+p2.getInViewY())/2;
109 double x = centerX - 4*strlen;
110 double y = centerY + 4;
111
112 if (virtualNodeSize != 0 && isLargeSegment(p1, p2, virtualNodeSpace)) {
113 y = centerY - virtualNodeSize - 3;
114 }
115
116 g.setColor(backgroundColor);
117 g.fill(new Rectangle2D.Double(x-1, y-12, 8*strlen+1, 14));
118 g.setColor(clr);
119 g.drawString(on, (int) x, (int) y);
120 }
121 }
122
123 /**
124 * Draws virtual nodes.
125 *
126 * @param data The data set being rendered.
127 * @param bbox The bounding box being displayed.
128 */
129 public void drawVirtualNodes(DataSet data, BBox bbox) {
130 if (virtualNodeSize == 0 || data == null || bbox == null)
131 return;
132 // print normal virtual nodes
133 GeneralPath path = new GeneralPath();
134 for (Way osm : data.searchWays(bbox)) {
135 if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) {
136 visitVirtual(path, osm);
137 }
138 }
139 g.setColor(nodeColor);
140 g.draw(path);
141 try {
142 // print highlighted virtual nodes. Since only the color changes, simply
143 // drawing them over the existing ones works fine (at least in their current simple style)
144 path = new GeneralPath();
145 for (WaySegment wseg: data.getHighlightedVirtualNodes()) {
146 if (wseg.way.isUsable() && !wseg.way.isDisabled()) {
147 visitVirtual(path, wseg.toWay());
148 }
149 }
150 g.setColor(highlightColor);
151 g.draw(path);
152 } catch (ArrayIndexOutOfBoundsException e) {
153 // Silently ignore any ArrayIndexOutOfBoundsException that may be raised
154 // if the way has changed while being rendered (fix #7979)
155 // TODO: proper solution ?
156 // Idea from bastiK:
157 // avoid the WaySegment class and add another data class with { Way way; Node firstNode, secondNode; int firstIdx; }.
158 // On read, it would first check, if the way still has firstIdx+2 nodes, then check if the corresponding way nodes are still
159 // the same and report changes in a more controlled manner.
160 Logging.trace(e);
161 }
162 }
163
164 /**
165 * Reads the color definitions from preferences. This function is <code>public</code>, so that
166 * color names in preferences can be displayed even without calling the wireframe display before.
167 */
168 public void getColors() {
169 this.backgroundColor = PaintColors.BACKGROUND.get();
170 this.inactiveColor = PaintColors.INACTIVE.get();
171 this.selectedColor = PaintColors.SELECTED.get();
172 this.relationSelectedColor = PaintColors.RELATIONSELECTED.get();
173 this.nodeColor = PaintColors.NODE.get();
174 this.highlightColor = PaintColors.HIGHLIGHT.get();
175 }
176
177 /**
178 * Reads all the settings from preferences. Calls the @{link #getColors}
179 * function.
180 *
181 * @param virtual <code>true</code> if virtual nodes are used
182 */
183 protected void getSettings(boolean virtual) {
184 this.virtualNodeSize = virtual ? Main.pref.getInteger("mappaint.node.virtual-size", 8) / 2 : 0;
185 this.virtualNodeSpace = Main.pref.getInteger("mappaint.node.virtual-space", 70);
186 this.segmentNumberSpace = Main.pref.getInteger("mappaint.segmentnumber.space", 40);
187 getColors();
188 }
189
190 /**
191 * Checks if a way segemnt is large enough for additional information display.
192 *
193 * @param p1 First point of the way segment.
194 * @param p2 Second point of the way segment.
195 * @param space The free space to check against.
196 * @return <code>true</code> if segment is larger than required space
197 * @since 10827
198 */
199 public static boolean isLargeSegment(MapViewPoint p1, MapViewPoint p2, int space) {
200 return p1.oneNormInView(p2) > space;
201 }
202
203 /**
204 * Checks if segment is visible in display.
205 *
206 * @param p1 First point of the way segment.
207 * @param p2 Second point of the way segment.
208 * @return <code>true</code> if segment may be visible.
209 * @since 10827
210 */
211 protected boolean isSegmentVisible(MapViewPoint p1, MapViewPoint p2) {
212 MapViewRectangle view = mapState.getViewArea();
213 // not outside in the same direction
214 return (p1.getOutsideRectangleFlags(view) & p2.getOutsideRectangleFlags(view)) == 0;
215 }
216
217 /**
218 * Creates path for drawing virtual nodes for one way.
219 *
220 * @param path The path to append drawing to.
221 * @param w The ways to draw node for.
222 * @since 10827
223 */
224 public void visitVirtual(Path2D path, Way w) {
225 Iterator<Node> it = w.getNodes().iterator();
226 MapViewPoint lastP = null;
227 while (it.hasNext()) {
228 Node n = it.next();
229 if (n.isLatLonKnown()) {
230 MapViewPoint p = mapState.getPointFor(n);
231 if (lastP != null && isSegmentVisible(lastP, p) && isLargeSegment(lastP, p, virtualNodeSpace)) {
232 double x = (p.getInViewX()+lastP.getInViewX())/2;
233 double y = (p.getInViewY()+lastP.getInViewY())/2;
234 path.moveTo(x-virtualNodeSize, y);
235 path.lineTo(x+virtualNodeSize, y);
236 path.moveTo(x, y-virtualNodeSize);
237 path.lineTo(x, y+virtualNodeSize);
238 }
239 lastP = p;
240 }
241 }
242 }
243}
Note: See TracBrowser for help on using the repository browser.