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

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

checkstyle: blocks

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