source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java@ 597

Last change on this file since 597 was 597, checked in by ramack, 16 years ago
  • implement ticket #671: add option to draw only interesting direction arrows, where interesting means: they way is tagged with a key oneway, incline, incline_steep or aerialway
File size: 7.2 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.data.osm.visitor;
3
4import java.awt.Color;
5import java.awt.Graphics;
6import java.awt.Graphics2D;
7import java.awt.Point;
8import java.awt.Rectangle;
9import java.awt.geom.GeneralPath;
10
11import java.util.Iterator;
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.data.osm.DataSet;
14import org.openstreetmap.josm.data.osm.Relation;
15import org.openstreetmap.josm.data.osm.Node;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.Way;
18import org.openstreetmap.josm.gui.NavigatableComponent;
19import org.openstreetmap.josm.tools.ColorHelper;
20
21/**
22 * A visitor that paints a simple scheme of every primitive it visits to a
23 * previous set graphic environment.
24 *
25 * @author imi
26 */
27public class SimplePaintVisitor implements Visitor {
28
29 public final static Color darkerblue = new Color(0,0,96);
30 public final static Color darkblue = new Color(0,0,128);
31 public final static Color darkgreen = new Color(0,128,0);
32
33 /**
34 * The environment to paint to.
35 */
36 protected Graphics g;
37 /**
38 * MapView to get screen coordinates.
39 */
40 protected NavigatableComponent nc;
41
42 public boolean inactive;
43
44 protected static final double PHI = Math.toRadians(20);
45
46 /**
47 * Preferences
48 */
49 protected Color inactiveColor;
50 protected Color selectedColor;
51 protected Color nodeColor;
52 protected Color dfltWayColor;
53 protected Color untaggedWayColor;
54 protected Color incompleteColor;
55 protected Color backgroundColor;
56 protected boolean showDirectionArrow;
57 protected boolean showRelevantDirectionsOnly;
58 protected boolean showOrderNumber;
59
60 /**
61 * Draw subsequent segments of same color as one Path
62 */
63 protected Color currentColor = null;
64 protected GeneralPath currentPath = new GeneralPath();
65
66 private Rectangle screen;
67 Rectangle bbox = new Rectangle();
68
69 public void visitAll(DataSet data) {
70 inactiveColor = getPreferencesColor("inactive", Color.DARK_GRAY);
71 selectedColor = getPreferencesColor("selected", Color.WHITE);
72 nodeColor = getPreferencesColor("node", Color.RED);
73 dfltWayColor = getPreferencesColor("way", darkblue);
74 untaggedWayColor = getPreferencesColor("untagged way", darkgreen);
75 incompleteColor = getPreferencesColor("incomplete way", darkerblue);
76 backgroundColor = getPreferencesColor("background", Color.BLACK);
77 showDirectionArrow = Main.pref.getBoolean("draw.segment.direction");
78 showRelevantDirectionsOnly = Main.pref.getBoolean("draw.segment.relevant_directions_only");
79 showOrderNumber = Main.pref.getBoolean("draw.segment.order_number");
80
81 // draw tagged ways first, then untagged ways. takes
82 // time to iterate through list twice, OTOH does not
83 // require changing the colour while painting...
84 for (final OsmPrimitive osm : data.ways)
85 if (!osm.deleted && !osm.selected && osm.tagged)
86 osm.visit(this);
87 displaySegments(null);
88
89 for (final OsmPrimitive osm : data.ways)
90 if (!osm.deleted && !osm.selected && !osm.tagged)
91 osm.visit(this);
92 displaySegments(null);
93
94 for (final OsmPrimitive osm : data.nodes)
95 if (!osm.deleted && !osm.selected)
96 osm.visit(this);
97
98 for (final OsmPrimitive osm : data.getSelected())
99 if (!osm.deleted)
100 osm.visit(this);
101 displaySegments(null);
102 }
103
104 /**
105 * Draw a small rectangle.
106 * White if selected (as always) or red otherwise.
107 *
108 * @param n The node to draw.
109 */
110 public void visit(Node n) {
111 if (n.incomplete) return;
112
113 Color color = null;
114 if (inactive)
115 color = inactiveColor;
116 else if (n.selected)
117 color = selectedColor;
118 else
119 color = nodeColor;
120 drawNode(n, color);
121 }
122
123 /**
124 * Draw a darkblue line for all segments.
125 * @param w The way to draw.
126 */
127 public void visit(Way w) {
128 if (w.incomplete) return;
129
130 // show direction arrows, if draw.segment.relevant_directions_only is not set, the way is tagged with a direction key
131 // (even if the tag is negated as in oneway=false) or the way is selected
132
133 boolean showThisDirectionArrow = w.selected
134 || (showDirectionArrow
135 && (!showRelevantDirectionsOnly || w.hasDirectionKeys));
136 Color wayColor;
137
138 if (inactive) {
139 wayColor = inactiveColor;
140 } else if (!w.tagged) {
141 wayColor = untaggedWayColor;
142 } else {
143 wayColor = dfltWayColor;
144 }
145
146 Iterator<Node> it = w.nodes.iterator();
147 if (it.hasNext()) {
148 Point lastP = nc.getPoint(it.next().eastNorth);
149 for (int orderNumber = 1; it.hasNext(); orderNumber++) {
150 Point p = nc.getPoint(it.next().eastNorth);
151 drawSegment(lastP, p, w.selected && !inactive ? selectedColor : wayColor, showThisDirectionArrow);
152 if (showOrderNumber)
153 drawOrderNumber(lastP, p, orderNumber);
154 lastP = p;
155 }
156 }
157 }
158
159 public void visit(Relation e) {
160 // relations are not (yet?) drawn.
161 }
162
163 /**
164 * Draw an number of the order of the two consecutive nodes within the
165 * parents way
166 */
167 protected void drawOrderNumber(Point p1, Point p2, int orderNumber) {
168 int strlen = (""+orderNumber).length();
169 int x = (p1.x+p2.x)/2 - 4*strlen;
170 int y = (p1.y+p2.y)/2 + 4;
171
172 if (screen.contains(x,y)) {
173 Color c = g.getColor();
174 g.setColor(backgroundColor);
175 g.fillRect(x-1, y-12, 8*strlen+1, 14);
176 g.setColor(c);
177 g.drawString(""+orderNumber, x, y);
178 }
179 }
180
181 /**
182 * Draw the node as small rectangle with the given color.
183 *
184 * @param n The node to draw.
185 * @param color The color of the node.
186 */
187 public void drawNode(Node n, Color color) {
188 Point p = nc.getPoint(n.eastNorth);
189 g.setColor(color);
190
191 if (screen.contains(p.x, p.y))
192 if (n.tagged) {
193 g.drawRect(p.x, p.y, 0, 0);
194 g.drawRect(p.x-2, p.y-2, 4, 4);
195 } else {
196 g.drawRect(p.x-1, p.y-1, 2, 2);
197 }
198 }
199
200 /**
201 * Draw a line with the given color.
202 */
203 protected void drawSegment(Point p1, Point p2, Color col, boolean showDirection) {
204
205 if (col != currentColor) displaySegments(col);
206
207 if (onScreen(p1, p2)) {
208 currentPath.moveTo(p1.x, p1.y);
209 currentPath.lineTo(p2.x, p2.y);
210
211 if (showDirection) {
212 double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
213 currentPath.lineTo((int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
214 currentPath.moveTo((int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
215 currentPath.lineTo(p2.x, p2.y);
216 }
217 }
218 }
219
220 private boolean onScreen(Point p1, Point p2) {
221 bbox.setBounds(p1.x, p1.y, 0, 0);
222 bbox.add(p2);
223 if (bbox.height + bbox.width < 1) return false;
224 bbox.width++;
225 bbox.height++;
226 return screen.intersects(bbox);
227 }
228
229 public static Color getPreferencesColor(String colName, Color def) {
230 String colStr = Main.pref.get("color."+colName);
231 if (colStr.equals("")) {
232 Main.pref.put("color."+colName, ColorHelper.color2html(def));
233 return def;
234 }
235 return ColorHelper.html2color(colStr);
236 }
237
238 public void setGraphics(Graphics g) {
239 this.g = g;
240 screen = g.getClipBounds();
241 }
242
243 public void setNavigatableComponent(NavigatableComponent nc) {
244 this.nc = nc;
245 }
246
247 protected void displaySegments(Color newColor) {
248 if (currentPath != null) {
249 g.setColor(currentColor);
250 ((Graphics2D) g).draw(currentPath);
251 currentPath = new GeneralPath();
252 currentColor = newColor;
253 }
254 }
255}
Note: See TracBrowser for help on using the repository browser.