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

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

fix squid:RedundantThrowsDeclarationCheck + consistent Javadoc for exceptions

  • Property svn:eol-style set to native
File size: 9.0 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 }
147 }
148
149 /**
150 * Reads the color definitions from preferences. This function is <code>public</code>, so that
151 * color names in preferences can be displayed even without calling the wireframe display before.
152 */
153 public void getColors() {
154 this.backgroundColor = PaintColors.BACKGROUND.get();
155 this.inactiveColor = PaintColors.INACTIVE.get();
156 this.selectedColor = PaintColors.SELECTED.get();
157 this.relationSelectedColor = PaintColors.RELATIONSELECTED.get();
158 this.nodeColor = PaintColors.NODE.get();
159 this.highlightColor = PaintColors.HIGHLIGHT.get();
160 }
161
162 /**
163 * Reads all the settings from preferences. Calls the @{link #getColors}
164 * function.
165 *
166 * @param virtual <code>true</code> if virtual nodes are used
167 */
168 protected void getSettings(boolean virtual) {
169 this.virtualNodeSize = virtual ? Main.pref.getInteger("mappaint.node.virtual-size", 8) / 2 : 0;
170 this.virtualNodeSpace = Main.pref.getInteger("mappaint.node.virtual-space", 70);
171 this.segmentNumberSpace = Main.pref.getInteger("mappaint.segmentnumber.space", 40);
172 getColors();
173 }
174
175 /**
176 * Checks if a way segemnt is large enough for additional information display.
177 *
178 * @param p1 First point of the way segment.
179 * @param p2 Second point of the way segment.
180 * @param space The free space to check against.
181 * @return <code>true</code> if segment is larger than required space
182 */
183 public static boolean isLargeSegment(Point2D p1, Point2D p2, int space) {
184 double xd = Math.abs(p1.getX()-p2.getX());
185 double yd = Math.abs(p1.getY()-p2.getY());
186 return (xd+yd > space);
187 }
188
189 /**
190 * Checks if segment is visible in display.
191 *
192 * @param p1 First point of the way segment.
193 * @param p2 Second point of the way segment.
194 * @return <code>true</code> if segment is visible.
195 */
196 protected boolean isSegmentVisible(Point p1, Point p2) {
197 if ((p1.x < 0) && (p2.x < 0)) return false;
198 if ((p1.y < 0) && (p2.y < 0)) return false;
199 if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false;
200 if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false;
201 return true;
202 }
203
204 /**
205 * Creates path for drawing virtual nodes for one way.
206 *
207 * @param path The path to append drawing to.
208 * @param w The ways to draw node for.
209 */
210 public void visitVirtual(GeneralPath path, Way w) {
211 Iterator<Node> it = w.getNodes().iterator();
212 if (it.hasNext()) {
213 Point lastP = nc.getPoint(it.next());
214 while (it.hasNext())
215 {
216 Point p = nc.getPoint(it.next());
217 if (isSegmentVisible(lastP, p) && isLargeSegment(lastP, p, virtualNodeSpace))
218 {
219 int x = (p.x+lastP.x)/2;
220 int y = (p.y+lastP.y)/2;
221 path.moveTo(x-virtualNodeSize, y);
222 path.lineTo(x+virtualNodeSize, y);
223 path.moveTo(x, y-virtualNodeSize);
224 path.lineTo(x, y+virtualNodeSize);
225 }
226 lastP = p;
227 }
228 }
229 }
230}
Note: See TracBrowser for help on using the repository browser.