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

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

fix #12634 - Make filled area of validation layer transparent (patch by michael2402)

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