source: josm/trunk/src/org/openstreetmap/josm/gui/layer/validation/PaintVisitor.java@ 12823

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

see #15229 - see #15182 - move PaintVisitor from data.validation to gui.layer.validation

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