source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java@ 2667

Last change on this file since 2667 was 2667, checked in by jttt, 14 years ago

Split MapPaintVisitor into two classes - MapPainter do the actual drawing while MapPaintVisitor choose style

  • Property svn:mime-type set to text/plain
File size: 9.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm.visitor.paint;
3
4import java.awt.BasicStroke;
5import java.awt.Color;
6import java.awt.Font;
7import java.awt.FontMetrics;
8import java.awt.Graphics2D;
9import java.awt.Image;
10import java.awt.Point;
11import java.awt.Polygon;
12import java.awt.Rectangle;
13import java.awt.geom.GeneralPath;
14import java.awt.geom.Rectangle2D;
15import java.util.Iterator;
16
17import javax.swing.ImageIcon;
18
19import org.openstreetmap.josm.Main;
20import org.openstreetmap.josm.data.osm.Node;
21import org.openstreetmap.josm.data.osm.Way;
22import org.openstreetmap.josm.gui.NavigatableComponent;
23import org.openstreetmap.josm.tools.ImageProvider;
24
25public class MapPainter {
26 private static final double PHI = Math.toRadians(20);
27
28 private final Graphics2D g;
29 private final NavigatableComponent nc;
30 private final boolean inactive;
31 private final boolean useStrokes;
32
33 private final Color inactiveColor;
34 private final Color textColor;
35 private final Color selectedColor;
36 private final Color areaTextColor;
37
38 private Font orderFont;
39 private int fillAlpha;
40
41 public MapPainter(Graphics2D g, boolean inactive, NavigatableComponent nc, boolean useStrokes) {
42 this.g = g;
43 this.inactive = inactive;
44 this.nc = nc;
45 this.useStrokes = useStrokes;
46
47 this.inactiveColor = PaintColors.INACTIVE.get();
48 this.textColor = PaintColors.TEXT.get();
49 this.selectedColor = PaintColors.SELECTED.get();
50 this.areaTextColor = PaintColors.AREA_TEXT.get();
51
52 this.orderFont = new Font(Main.pref.get("mappaint.font", "Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8));
53 this.fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref.getInteger("mappaint.fillalpha", 50))));
54 }
55
56 public void drawWay(Way way, Color color, int width, float dashed[], Color dashedColor, boolean showDirection,
57 boolean showHeadArrowOnly) {
58
59 GeneralPath path = new GeneralPath();
60
61 Point lastPoint = null;
62 Iterator<Node> it = way.getNodes().iterator();
63 while (it.hasNext()) {
64 Node n = it.next();
65 Point p = nc.getPoint(n);
66 if(lastPoint != null) {
67 drawSegment(path, lastPoint, p, (showHeadArrowOnly ? !it.hasNext() : showDirection));
68 }
69 lastPoint = p;
70 }
71 displaySegments(path, color, width, dashed, dashedColor);
72 }
73
74 private void displaySegments(GeneralPath path, Color color, int width, float dashed[], Color dashedColor) {
75 g.setColor(inactive ? inactiveColor : color);
76 if (useStrokes) {
77 if (dashed.length > 0) {
78 g.setStroke(new BasicStroke(width,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0, dashed,0));
79 } else {
80 g.setStroke(new BasicStroke(width,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
81 }
82 }
83 g.draw(path);
84
85 if(!inactive && useStrokes && dashedColor != null) {
86 g.setColor(dashedColor);
87 if (dashed.length > 0) {
88 float[] dashedOffset = new float[dashed.length];
89 System.arraycopy(dashed, 1, dashedOffset, 0, dashed.length - 1);
90 dashedOffset[dashed.length-1] = dashed[0];
91 float offset = dashedOffset[0];
92 g.setStroke(new BasicStroke(width,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,dashedOffset,offset));
93 } else {
94 g.setStroke(new BasicStroke(width,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
95 }
96 g.draw(path);
97 }
98
99 if(useStrokes) {
100 g.setStroke(new BasicStroke());
101 }
102 }
103
104 private void drawSegment(GeneralPath path, Point p1, Point p2, boolean showDirection) {
105 if (isSegmentVisible(p1, p2)) {
106 path.moveTo(p1.x, p1.y);
107 path.lineTo(p2.x, p2.y);
108
109 if (showDirection) {
110 double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
111 path.lineTo((int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
112 path.moveTo((int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
113 path.lineTo(p2.x, p2.y);
114 }
115 }
116 }
117
118 private boolean isSegmentVisible(Point p1, Point p2) {
119 if ((p1.x < 0) && (p2.x < 0)) return false;
120 if ((p1.y < 0) && (p2.y < 0)) return false;
121 if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false;
122 if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false;
123 return true;
124 }
125
126
127 protected void drawNodeIcon(Node n, ImageIcon icon, boolean annotate, boolean selected, String name) {
128 Point p = nc.getPoint(n);
129 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
130
131 int w = icon.getIconWidth(), h=icon.getIconHeight();
132 icon.paintIcon ( Main.map.mapView, g, p.x-w/2, p.y-h/2 );
133 if(name != null) {
134 if (inactive || n.isDisabled()) {
135 g.setColor(inactiveColor);
136 } else {
137 g.setColor(textColor);
138 }
139 Font defaultFont = g.getFont();
140 g.setFont (orderFont);
141 g.drawString (name, p.x+w/2+2, p.y+h/2+2);
142 g.setFont(defaultFont);
143 }
144 if (selected)
145 {
146 g.setColor ( selectedColor );
147 g.drawRect (p.x-w/2-2, p.y-h/2-2, w+4, h+4);
148 }
149 }
150
151
152 /**
153 * Draw the node as small rectangle with the given color.
154 *
155 * @param n The node to draw.
156 * @param color The color of the node.
157 */
158 public void drawNode(Node n, Color color, int size, int radius, boolean fill, String name) {
159 if (size > 1) {
160 Point p = nc.getPoint(n);
161 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth())
162 || (p.y > nc.getHeight()))
163 return;
164
165 if (inactive || n.isDisabled()) {
166 g.setColor(inactiveColor);
167 } else {
168 g.setColor(color);
169 }
170 if (fill) {
171 g.fillRect(p.x - radius, p.y - radius, size, size);
172 g.drawRect(p.x - radius, p.y - radius, size, size);
173 } else {
174 g.drawRect(p.x - radius, p.y - radius, size, size);
175 }
176
177 if(name != null) {
178 if (inactive || n.isDisabled()) {
179 g.setColor(inactiveColor);
180 } else {
181 g.setColor(textColor);
182 }
183 Font defaultFont = g.getFont();
184 g.setFont (orderFont);
185 g.drawString (name, p.x+radius+2, p.y+radius+2);
186 g.setFont(defaultFont);
187 }
188 }
189 }
190
191 protected void drawArea(Polygon polygon, Color color, String name) {
192
193 /* set the opacity (alpha) level of the filled polygon */
194 g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
195 g.fillPolygon(polygon);
196
197 if (name != null) {
198 Rectangle pb = polygon.getBounds();
199 FontMetrics fontMetrics = g.getFontMetrics(orderFont); // if slow, use cache
200 Rectangle2D nb = fontMetrics.getStringBounds(name, g); // if slow, approximate by strlen()*maxcharbounds(font)
201
202 // Point2D c = getCentroid(polygon);
203 // Using the Centroid is Nicer for buildings like: +--------+
204 // but this needs to be fast. As most houses are | 42 |
205 // boxes anyway, the center of the bounding box +---++---+
206 // will have to do. ++
207 // Centroids are not optimal either, just imagine a U-shaped house.
208 // Point2D c = new Point2D.Double(pb.x + pb.width / 2.0, pb.y + pb.height / 2.0);
209 // Rectangle2D.Double centeredNBounds =
210 // new Rectangle2D.Double(c.getX() - nb.getWidth()/2,
211 // c.getY() - nb.getHeight()/2,
212 // nb.getWidth(),
213 // nb.getHeight());
214
215 Rectangle centeredNBounds = new Rectangle(pb.x + (int)((pb.width - nb.getWidth())/2.0),
216 pb.y + (int)((pb.height - nb.getHeight())/2.0),
217 (int)nb.getWidth(),
218 (int)nb.getHeight());
219
220 if ((pb.width >= nb.getWidth() && pb.height >= nb.getHeight()) && // quick check
221 polygon.contains(centeredNBounds) // slow but nice
222 ) {
223 g.setColor(areaTextColor);
224 Font defaultFont = g.getFont();
225 g.setFont (orderFont);
226 g.drawString (name,
227 (int)(centeredNBounds.getMinX() - nb.getMinX()),
228 (int)(centeredNBounds.getMinY() - nb.getMinY()));
229 g.setFont(defaultFont);
230 }
231 }
232 }
233
234 public void drawRestriction(ImageIcon icon, Point pVia, double vx, double vx2, double vy, double vy2, double iconAngle, boolean selected) {
235 /* rotate icon with direction last node in from to */
236 ImageIcon rotatedIcon = ImageProvider.createRotatedImage(null /*icon2*/, icon, iconAngle);
237
238 /* scale down icon to 16*16 pixels */
239 ImageIcon smallIcon = new ImageIcon(rotatedIcon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH));
240 int w = smallIcon.getIconWidth(), h=smallIcon.getIconHeight();
241 smallIcon.paintIcon (nc, g, (int)(pVia.x+vx+vx2)-w/2, (int)(pVia.y+vy+vy2)-h/2 );
242
243 if (selected) {
244 g.setColor(selectedColor);
245 g.drawRect((int)(pVia.x+vx+vx2)-w/2-2,(int)(pVia.y+vy+vy2)-h/2-2, w+4, h+4);
246 }
247 }
248
249}
Note: See TracBrowser for help on using the repository browser.