source: josm/trunk/src/org/openstreetmap/josm/data/validation/PaintVisitor.java@ 7937

Last change on this file since 7937 was 7937, checked in by bastiK, 9 years ago

add subversion property svn:eol=native

  • Property svn:eol-style set to native
File size: 8.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.validation;
3
4import java.awt.Color;
5import java.awt.Graphics;
6import java.awt.Point;
7import java.util.HashSet;
8import java.util.List;
9import java.util.Set;
10
11import org.openstreetmap.josm.data.coor.LatLon;
12import org.openstreetmap.josm.data.osm.Node;
13import org.openstreetmap.josm.data.osm.OsmPrimitive;
14import org.openstreetmap.josm.data.osm.Relation;
15import org.openstreetmap.josm.data.osm.Way;
16import org.openstreetmap.josm.data.osm.WaySegment;
17import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
18import org.openstreetmap.josm.gui.MapView;
19
20/**
21 * Visitor that highlights the primitives affected by an error
22 * @author frsantos
23 * @since 5671
24 */
25public class PaintVisitor extends AbstractVisitor implements ValidatorVisitor {
26 /** The graphics */
27 private final Graphics g;
28 /** The MapView */
29 private final MapView mv;
30
31 /** The severity color */
32 private Color color;
33 /** Is the error selected ? */
34 private boolean selected;
35
36 private final Set<PaintedPoint> paintedPoints = new HashSet<>();
37 private final Set<PaintedSegment> paintedSegments = new HashSet<>();
38
39 /**
40 * Constructor
41 * @param g The graphics
42 * @param mv The Mapview
43 */
44 public PaintVisitor(Graphics g, MapView mv) {
45 this.g = g;
46 this.mv = mv;
47 }
48
49 protected static class PaintedPoint {
50 protected final LatLon p1;
51 protected final Color color;
52
53 public PaintedPoint(LatLon p1, Color color) {
54 this.p1 = p1;
55 this.color = color;
56 }
57
58 @Override
59 public int hashCode() {
60 final int prime = 31;
61 int result = 1;
62 result = prime * result + p1.hashCode();
63 result = prime * result + color.hashCode();
64 return result;
65 }
66
67 @Override
68 public boolean equals(Object obj) {
69 if (this == obj)
70 return true;
71 if (obj == null)
72 return false;
73 if (getClass() != obj.getClass())
74 return false;
75 PaintedPoint other = (PaintedPoint) obj;
76 if (!p1.equals(other.p1))
77 return false;
78 if (!color.equals(other.color))
79 return false;
80 return true;
81 }
82 }
83
84 protected static class PaintedSegment extends PaintedPoint {
85 final LatLon p2;
86
87 public PaintedSegment(LatLon p1, LatLon p2, Color color) {
88 super(p1, color);
89 this.p2 = p2;
90 }
91
92 @Override
93 public int hashCode() {
94 final int prime = 31;
95 int result = super.hashCode();
96 result = prime * result + p2.hashCode();
97 return result;
98 }
99
100 @Override
101 public boolean equals(Object obj) {
102 if (!super.equals(obj)) {
103 return false;
104 }
105 PaintedSegment other = (PaintedSegment) obj;
106 if (!p2.equals(other.p2))
107 return false;
108 return true;
109 }
110 }
111
112 @Override
113 public void visit(TestError error) {
114 if (error != null && !error.getIgnored()) {
115 color = error.getSeverity().getColor();
116 selected = error.isSelected();
117 error.visitHighlighted(this);
118 }
119 }
120
121 @Override
122 public void visit(OsmPrimitive p) {
123 if (p.isUsable()) {
124 p.accept(this);
125 }
126 }
127
128 /**
129 * Draws a circle around the node
130 * @param n The node
131 * @param color The circle color
132 */
133 protected void drawNode(Node n, Color color) {
134 PaintedPoint pp = new PaintedPoint(n.getCoor(), color);
135
136 if (!paintedPoints.contains(pp)) {
137 Point p = mv.getPoint(n);
138 g.setColor(color);
139
140 if (selected) {
141 g.fillOval(p.x - 5, p.y - 5, 10, 10);
142 } else {
143 g.drawOval(p.x - 5, p.y - 5, 10, 10);
144 }
145 paintedPoints.add(pp);
146 }
147 }
148
149 /**
150 * Draws a line around the segment
151 *
152 * @param p1 The first point of segment
153 * @param p2 The second point of segment
154 * @param color The color
155 */
156 protected void drawSegment(Point p1, Point p2, Color color) {
157 g.setColor(color);
158
159 double t = Math.atan2(p2.x - p1.x, p2.y - p1.y);
160 double cosT = 5 * Math.cos(t);
161 double sinT = 5 * Math.sin(t);
162 int deg = (int) Math.toDegrees(t);
163 if (selected) {
164 int[] x = new int[] { (int) (p1.x + cosT), (int) (p2.x + cosT),
165 (int) (p2.x - cosT), (int) (p1.x - cosT) };
166 int[] y = new int[] { (int) (p1.y - sinT), (int) (p2.y - sinT),
167 (int) (p2.y + sinT), (int) (p1.y + sinT) };
168 g.fillPolygon(x, y, 4);
169 g.fillArc(p1.x - 5, p1.y - 5, 10, 10, deg, 180);
170 g.fillArc(p2.x - 5, p2.y - 5, 10, 10, deg, -180);
171 } else {
172 g.drawLine((int) (p1.x + cosT), (int) (p1.y - sinT),
173 (int) (p2.x + cosT), (int) (p2.y - sinT));
174 g.drawLine((int) (p1.x - cosT), (int) (p1.y + sinT),
175 (int) (p2.x - cosT), (int) (p2.y + sinT));
176 g.drawArc(p1.x - 5, p1.y - 5, 10, 10, deg, 180);
177 g.drawArc(p2.x - 5, p2.y - 5, 10, 10, deg, -180);
178 }
179 }
180
181 /**
182 * Draws a line around the segment
183 *
184 * @param n1 The first node of segment
185 * @param n2 The second node of segment
186 * @param color The color
187 */
188 protected void drawSegment(Node n1, Node n2, Color color) {
189 if (n1.isDrawable() && n2.isDrawable() && isSegmentVisible(n1, n2)) {
190 PaintedSegment ps = new PaintedSegment(n1.getCoor(), n2.getCoor(), color);
191 if (!paintedSegments.contains(ps)) {
192 drawSegment(mv.getPoint(n1), mv.getPoint(n2), color);
193 paintedSegments.add(ps);
194 }
195 }
196 }
197
198 /**
199 * Draw a small rectangle.
200 * White if selected (as always) or red otherwise.
201 *
202 * @param n The node to draw.
203 */
204 @Override
205 public void visit(Node n) {
206 if (n.isDrawable() && isNodeVisible(n)) {
207 drawNode(n, color);
208 }
209 }
210
211 @Override
212 public void visit(Way w) {
213 visit(w.getNodes());
214 }
215
216 @Override
217 public void visit(WaySegment ws) {
218 if (ws.lowerIndex < 0 || ws.lowerIndex + 1 >= ws.way.getNodesCount())
219 return;
220 Node a = ws.way.getNodes().get(ws.lowerIndex);
221 Node b = ws.way.getNodes().get(ws.lowerIndex + 1);
222 drawSegment(a, b, color);
223 }
224
225 @Override
226 public void visit(Relation r) {
227 /* No idea how to draw a relation. */
228 }
229
230 /**
231 * Checks if the given node is in the visible area.
232 * @param n The node to check for visibility
233 * @return true if the node is visible
234 */
235 protected boolean isNodeVisible(Node n) {
236 Point p = mv.getPoint(n);
237 return !((p.x < 0) || (p.y < 0) || (p.x > mv.getWidth()) || (p.y > mv.getHeight()));
238 }
239
240 /**
241 * Checks if the given segment is in the visible area.
242 * NOTE: This will return true for a small number of non-visible
243 * segments.
244 * @param n1 The first point of the segment to check
245 * @param n2 The second point of the segment to check
246 * @return {@code true} if the segment is visible
247 */
248 protected boolean isSegmentVisible(Node n1, Node n2) {
249 Point p1 = mv.getPoint(n1);
250 Point p2 = mv.getPoint(n2);
251 if ((p1.x < 0) && (p2.x < 0))
252 return false;
253 if ((p1.y < 0) && (p2.y < 0))
254 return false;
255 if ((p1.x > mv.getWidth()) && (p2.x > mv.getWidth()))
256 return false;
257 if ((p1.y > mv.getHeight()) && (p2.y > mv.getHeight()))
258 return false;
259 return true;
260 }
261
262 @Override
263 public void visit(List<Node> nodes) {
264 Node lastN = null;
265 for (Node n : nodes) {
266 if (lastN == null) {
267 lastN = n;
268 continue;
269 }
270 drawSegment(lastN, n, color);
271 lastN = n;
272 }
273 }
274
275 /**
276 * Clears the internal painted objects collections.
277 */
278 public void clearPaintedObjects() {
279 paintedPoints.clear();
280 paintedSegments.clear();
281 }
282}
Note: See TracBrowser for help on using the repository browser.