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

Last change on this file since 3836 was 3836, checked in by bastiK, 13 years ago

mappaint restructuring aimed at mapcss support:

  • area- and line style of multipolygon outer & inner ways are no longer determined by MapPaintVisitor, but the information is calculated in advance and cached
  • cache is aware of zoom level
  • z_index property to allow more fancy styles in future

Performance: when the style cache is filled, painting is the same or ~5% faster. The first painting, which includes style generation, takes ~30% longer than before. (There is potential for optimization, though.) Memory usage unchanged.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/plain
File size: 24.2 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.Arrays;
16import java.util.Collection;
17import java.util.Iterator;
18
19import javax.swing.ImageIcon;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.data.osm.Node;
23import org.openstreetmap.josm.data.osm.OsmPrimitive;
24import org.openstreetmap.josm.data.osm.OsmUtils;
25import org.openstreetmap.josm.data.osm.Relation;
26import org.openstreetmap.josm.data.osm.RelationMember;
27import org.openstreetmap.josm.data.osm.Way;
28import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
29import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData;
30import org.openstreetmap.josm.gui.NavigatableComponent;
31import org.openstreetmap.josm.gui.mappaint.NodeElemStyle;
32import org.openstreetmap.josm.tools.ImageProvider;
33import org.openstreetmap.josm.tools.LanguageInfo;
34
35public class MapPainter {
36
37 private final Graphics2D g;
38 private final NavigatableComponent nc;
39 private final boolean inactive;
40
41 private final boolean useStrokes;
42 private final boolean showNames;
43 private final boolean showIcons;
44 private final boolean outlineOnly;
45
46 private final Color inactiveColor;
47 private final Color textColor;
48 private final Color selectedColor;
49 private final Color relationSelectedColor;
50 private final Color areaTextColor;
51 private final Color nodeColor;
52 private final Color backgroundColor;
53
54 private final Font orderFont;
55 private final int fillAlpha;
56 private final int virtualNodeSize;
57 private final int virtualNodeSpace;
58 private final int segmentNumberSpace;
59
60 private final double circum;
61
62 private final boolean leftHandTraffic;
63
64 private final Collection<String> regionalNameOrder;
65
66 private static final double PHI = Math.toRadians(20);
67 private static final double cosPHI = Math.cos(PHI);
68 private static final double sinPHI = Math.sin(PHI);
69
70 public MapPainter(MapPaintSettings settings, Graphics2D g,
71 boolean inactive, NavigatableComponent nc, boolean virtual,
72 double circum, boolean leftHandTraffic)
73 {
74 this.g = g;
75 this.inactive = inactive;
76 this.nc = nc;
77 this.useStrokes = settings.getUseStrokesDistance() > circum;
78 this.showNames = settings.getShowNamesDistance() > circum;
79 this.showIcons = settings.getShowIconsDistance() > circum;
80 this.outlineOnly = settings.isOutlineOnly();
81
82 this.inactiveColor = PaintColors.INACTIVE.get();
83 this.textColor = PaintColors.TEXT.get();
84 this.selectedColor = PaintColors.SELECTED.get();
85 this.relationSelectedColor = PaintColors.RELATIONSELECTED.get();
86 this.areaTextColor = PaintColors.AREA_TEXT.get();
87 this.nodeColor = PaintColors.NODE.get();
88 this.backgroundColor = PaintColors.BACKGROUND.get();
89
90 this.orderFont = new Font(Main.pref.get("mappaint.font", "Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8));
91 this.fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref.getInteger("mappaint.fillalpha", 50))));
92 this.virtualNodeSize = virtual ? Main.pref.getInteger("mappaint.node.virtual-size", 8) / 2 : 0;
93 this.virtualNodeSpace = Main.pref.getInteger("mappaint.node.virtual-space", 70);
94 this.segmentNumberSpace = Main.pref.getInteger("mappaint.segmentnumber.space", 40);
95
96 String[] names = {"name:" + LanguageInfo.getJOSMLocaleCode(), "name", "int_name", "ref", "operator", "brand", "addr:housenumber"};
97 this.regionalNameOrder = Main.pref.getCollection("mappaint.nameOrder", Arrays.asList(names));
98 this.circum = circum;
99 this.leftHandTraffic = leftHandTraffic;
100 }
101
102 public void drawWay(Way way, Color color, float width, float dashed[], Color dashedColor, boolean showDirection,
103 boolean reversedDirection, boolean showHeadArrowOnly) {
104
105 GeneralPath path = new GeneralPath();
106 GeneralPath arrows = new GeneralPath();
107 Rectangle bounds = g.getClipBounds();
108 bounds.grow(100, 100); // avoid arrow heads at the border
109
110 Point lastPoint = null;
111 boolean initialMoveToNeeded = true;
112 Iterator<Node> it = way.getNodes().iterator();
113 while (it.hasNext()) {
114 Node n = it.next();
115 Point p = nc.getPoint(n);
116 if(lastPoint != null) {
117 Point p1 = lastPoint;
118 Point p2 = p;
119
120 /**
121 * Do custom clipping to work around openjdk bug. It leads to
122 * drawing artefacts when zooming in a lot. (#4289, #4424)
123 * (Looks like int overflow.)
124 */
125 LineClip clip = new LineClip(p1, p2, bounds);
126 if (clip.execute()) {
127 if (!p1.equals(clip.getP1())) {
128 p1 = clip.getP1();
129 path.moveTo(p1.x, p1.y);
130 } else if (initialMoveToNeeded) {
131 initialMoveToNeeded = false;
132 path.moveTo(p1.x, p1.y);
133 }
134 p2 = clip.getP2();
135 path.lineTo(p2.x, p2.y);
136
137 /* draw arrow */
138 if (showHeadArrowOnly ? !it.hasNext() : showDirection) {
139 if (reversedDirection) {
140 Point tmp = p1;
141 p1 = p2;
142 p2 = tmp;
143 }
144 final double l = 10. / p1.distance(p2);
145
146 final double sx = l * (p1.x - p2.x);
147 final double sy = l * (p1.y - p2.y);
148
149 arrows.moveTo(p2.x, p2.y);
150 arrows.lineTo (p2.x + (int) Math.round(cosPHI * sx - sinPHI * sy), p2.y + (int) Math.round(sinPHI * sx + cosPHI * sy));
151 arrows.moveTo (p2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), p2.y + (int) Math.round(- sinPHI * sx + cosPHI * sy));
152 arrows.lineTo(p2.x, p2.y);
153 }
154 }
155 }
156 lastPoint = p;
157 }
158 displaySegments(path, arrows, color, width, dashed, dashedColor);
159 }
160
161 private void displaySegments(GeneralPath path, GeneralPath arrows, Color color, float width, float dashed[], Color dashedColor) {
162 g.setColor(inactive ? inactiveColor : color);
163 if (useStrokes) {
164 if (dashed == null || dashed.length > 0) {
165 g.setStroke(new BasicStroke(width,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0, dashed,0));
166 } else {
167 g.setStroke(new BasicStroke(width,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
168 }
169 }
170 g.draw(path);
171 g.draw(arrows);
172
173 if(!inactive && useStrokes && dashedColor != null) {
174 g.setColor(dashedColor);
175 if (dashed == null || dashed.length > 0) {
176 float[] dashedOffset = new float[dashed.length];
177 System.arraycopy(dashed, 1, dashedOffset, 0, dashed.length - 1);
178 dashedOffset[dashed.length-1] = dashed[0];
179 float offset = dashedOffset[0];
180 g.setStroke(new BasicStroke(width,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,dashedOffset,offset));
181 } else {
182 g.setStroke(new BasicStroke(width,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
183 }
184 g.draw(path);
185 g.draw(arrows);
186 }
187
188 if(useStrokes) {
189 g.setStroke(new BasicStroke());
190 }
191 }
192
193 private boolean isSegmentVisible(Point p1, Point p2) {
194 if ((p1.x < 0) && (p2.x < 0)) return false;
195 if ((p1.y < 0) && (p2.y < 0)) return false;
196 if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false;
197 if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false;
198 return true;
199 }
200
201 public void drawNodeIcon(Node n, ImageIcon icon, boolean selected, boolean member, String name) {
202 Point p = nc.getPoint(n);
203 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
204
205 int w = icon.getIconWidth(), h=icon.getIconHeight();
206 icon.paintIcon ( nc, g, p.x-w/2, p.y-h/2 );
207 if(name != null) {
208 if (inactive || n.isDisabled()) {
209 g.setColor(inactiveColor);
210 } else {
211 g.setColor(textColor);
212 }
213 Font defaultFont = g.getFont();
214 g.setFont (orderFont);
215 g.drawString (name, p.x+w/2+2, p.y+h/2+2);
216 g.setFont(defaultFont);
217 }
218 if (selected || member)
219 {
220 g.setColor(selected? selectedColor : relationSelectedColor);
221 g.drawRect(p.x-w/2-2, p.y-h/2-2, w+4, h+4);
222 }
223 }
224
225 /**
226 * Draw the node as small rectangle with the given color.
227 *
228 * @param n The node to draw.
229 * @param color The color of the node.
230 */
231 public void drawNode(Node n, Color color, int size, boolean fill, String name) {
232 if (size > 1) {
233 Point p = nc.getPoint(n);
234 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
235 int radius = size / 2;
236
237 if (inactive || n.isDisabled()) {
238 g.setColor(inactiveColor);
239 } else {
240 g.setColor(color);
241 }
242 if (fill) {
243 g.fillRect(p.x - radius, p.y - radius, size + 1, size + 1);
244 } else {
245 g.drawRect(p.x - radius, p.y - radius, size, size);
246 }
247
248 if(name != null) {
249 if (inactive || n.isDisabled()) {
250 g.setColor(inactiveColor);
251 } else {
252 g.setColor(textColor);
253 }
254 Font defaultFont = g.getFont();
255 g.setFont (orderFont);
256 g.drawString (name, p.x+radius+2, p.y+radius+2);
257 g.setFont(defaultFont);
258 }
259 }
260 }
261
262 private Polygon getPolygon(Way w) {
263 Polygon polygon = new Polygon();
264
265 for (Node n : w.getNodes()) {
266 Point p = nc.getPoint(n);
267 polygon.addPoint(p.x,p.y);
268 }
269 return polygon;
270 }
271
272 public void drawArea(Way w, Color color, String name) {
273 Polygon polygon = getPolygon(w);
274 drawArea(polygon, color, name);
275 }
276
277 protected void drawArea(Polygon polygon, Color color, String name) {
278
279 /* set the opacity (alpha) level of the filled polygon */
280 g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
281
282 if (outlineOnly) {
283 g.drawPolygon(polygon);
284 } else {
285 g.fillPolygon(polygon);
286 }
287
288
289 if (name != null) {
290 Rectangle pb = polygon.getBounds();
291 FontMetrics fontMetrics = g.getFontMetrics(orderFont); // if slow, use cache
292 Rectangle2D nb = fontMetrics.getStringBounds(name, g); // if slow, approximate by strlen()*maxcharbounds(font)
293
294 // Point2D c = getCentroid(polygon);
295 // Using the Centroid is Nicer for buildings like: +--------+
296 // but this needs to be fast. As most houses are | 42 |
297 // boxes anyway, the center of the bounding box +---++---+
298 // will have to do. ++
299 // Centroids are not optimal either, just imagine a U-shaped house.
300 // Point2D c = new Point2D.Double(pb.x + pb.width / 2.0, pb.y + pb.height / 2.0);
301 // Rectangle2D.Double centeredNBounds =
302 // new Rectangle2D.Double(c.getX() - nb.getWidth()/2,
303 // c.getY() - nb.getHeight()/2,
304 // nb.getWidth(),
305 // nb.getHeight());
306
307 Rectangle centeredNBounds = new Rectangle(pb.x + (int)((pb.width - nb.getWidth())/2.0),
308 pb.y + (int)((pb.height - nb.getHeight())/2.0),
309 (int)nb.getWidth(),
310 (int)nb.getHeight());
311
312 if ((pb.width >= nb.getWidth() && pb.height >= nb.getHeight()) && // quick check
313 polygon.contains(centeredNBounds) // slow but nice
314 ) {
315 g.setColor(areaTextColor);
316 Font defaultFont = g.getFont();
317 g.setFont (orderFont);
318 g.drawString (name,
319 (int)(centeredNBounds.getMinX() - nb.getMinX()),
320 (int)(centeredNBounds.getMinY() - nb.getMinY()));
321 g.setFont(defaultFont);
322 }
323 }
324 }
325
326 public void drawArea(Relation r, Color color, String name) {
327 Multipolygon multipolygon = new Multipolygon(nc);
328 multipolygon.load(r);
329 if(!r.isDisabled() && !multipolygon.getOuterWays().isEmpty()) {
330 for (PolyData pd : multipolygon.getCombinedPolygons()) {
331 Polygon p = pd.get();
332 if(!isPolygonVisible(p)) {
333 continue;
334 }
335 drawArea(p, color, getAreaName(r));
336 }
337 }
338 }
339
340 private boolean isPolygonVisible(Polygon polygon) {
341 Rectangle bounds = polygon.getBounds();
342 if (bounds.width == 0 && bounds.height == 0) return false;
343 if (bounds.x > nc.getWidth()) return false;
344 if (bounds.y > nc.getHeight()) return false;
345 if (bounds.x + bounds.width < 0) return false;
346 if (bounds.y + bounds.height < 0) return false;
347 return true;
348 }
349
350 public void drawRestriction(ImageIcon icon, Point pVia, double vx, double vx2, double vy, double vy2, double iconAngle, boolean selected) {
351 /* rotate icon with direction last node in from to */
352 ImageIcon rotatedIcon = ImageProvider.createRotatedImage(null /*icon2*/, icon, iconAngle);
353
354 /* scale down icon to 16*16 pixels */
355 ImageIcon smallIcon = new ImageIcon(rotatedIcon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH));
356 int w = smallIcon.getIconWidth(), h=smallIcon.getIconHeight();
357 smallIcon.paintIcon (nc, g, (int)(pVia.x+vx+vx2)-w/2, (int)(pVia.y+vy+vy2)-h/2 );
358
359 if (selected) {
360 g.setColor(relationSelectedColor);
361 g.drawRect((int)(pVia.x+vx+vx2)-w/2-2,(int)(pVia.y+vy+vy2)-h/2-2, w+4, h+4);
362 }
363 }
364
365 public void drawRestriction(Relation r, NodeElemStyle icon) {
366
367 Way fromWay = null;
368 Way toWay = null;
369 OsmPrimitive via = null;
370
371 /* find the "from", "via" and "to" elements */
372 for (RelationMember m : r.getMembers())
373 {
374 if(m.getMember().isIncomplete())
375 return;
376 else
377 {
378 if(m.isWay())
379 {
380 Way w = m.getWay();
381 if(w.getNodesCount() < 2) {
382 continue;
383 }
384
385 if("from".equals(m.getRole())) {
386 if(fromWay == null)
387 fromWay = w;
388 } else if("to".equals(m.getRole())) {
389 if(toWay == null)
390 toWay = w;
391 } else if("via".equals(m.getRole())) {
392 if(via == null)
393 via = w;
394 }
395 }
396 else if(m.isNode())
397 {
398 Node n = m.getNode();
399 if("via".equals(m.getRole()) && via == null)
400 via = n;
401 }
402 }
403 }
404
405 if (fromWay == null || toWay == null || via == null)
406 return;
407
408 Node viaNode;
409 if(via instanceof Node)
410 {
411 viaNode = (Node) via;
412 if(!fromWay.isFirstLastNode(viaNode)) {
413 return;
414 }
415 }
416 else
417 {
418 Way viaWay = (Way) via;
419 Node firstNode = viaWay.firstNode();
420 Node lastNode = viaWay.lastNode();
421 Boolean onewayvia = false;
422
423 String onewayviastr = viaWay.get("oneway");
424 if(onewayviastr != null)
425 {
426 if("-1".equals(onewayviastr)) {
427 onewayvia = true;
428 Node tmp = firstNode;
429 firstNode = lastNode;
430 lastNode = tmp;
431 } else {
432 onewayvia = OsmUtils.getOsmBoolean(onewayviastr);
433 if (onewayvia == null) {
434 onewayvia = false;
435 }
436 }
437 }
438
439 if(fromWay.isFirstLastNode(firstNode)) {
440 viaNode = firstNode;
441 } else if (!onewayvia && fromWay.isFirstLastNode(lastNode)) {
442 viaNode = lastNode;
443 } else {
444 return;
445 }
446 }
447
448 /* find the "direct" nodes before the via node */
449 Node fromNode = null;
450 if(fromWay.firstNode() == via) {
451 fromNode = fromWay.getNode(1);
452 } else {
453 fromNode = fromWay.getNode(fromWay.getNodesCount()-2);
454 }
455
456 Point pFrom = nc.getPoint(fromNode);
457 Point pVia = nc.getPoint(viaNode);
458
459 /* starting from via, go back the "from" way a few pixels
460 (calculate the vector vx/vy with the specified length and the direction
461 away from the "via" node along the first segment of the "from" way)
462 */
463 double distanceFromVia=14;
464 double dx = (pFrom.x >= pVia.x) ? (pFrom.x - pVia.x) : (pVia.x - pFrom.x);
465 double dy = (pFrom.y >= pVia.y) ? (pFrom.y - pVia.y) : (pVia.y - pFrom.y);
466
467 double fromAngle;
468 if(dx == 0.0) {
469 fromAngle = Math.PI/2;
470 } else {
471 fromAngle = Math.atan(dy / dx);
472 }
473 double fromAngleDeg = Math.toDegrees(fromAngle);
474
475 double vx = distanceFromVia * Math.cos(fromAngle);
476 double vy = distanceFromVia * Math.sin(fromAngle);
477
478 if(pFrom.x < pVia.x) {
479 vx = -vx;
480 }
481 if(pFrom.y < pVia.y) {
482 vy = -vy;
483 }
484
485 /* go a few pixels away from the way (in a right angle)
486 (calculate the vx2/vy2 vector with the specified length and the direction
487 90degrees away from the first segment of the "from" way)
488 */
489 double distanceFromWay=10;
490 double vx2 = 0;
491 double vy2 = 0;
492 double iconAngle = 0;
493
494 if(pFrom.x >= pVia.x && pFrom.y >= pVia.y) {
495 if(!leftHandTraffic) {
496 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90));
497 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90));
498 } else {
499 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90));
500 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90));
501 }
502 iconAngle = 270+fromAngleDeg;
503 }
504 if(pFrom.x < pVia.x && pFrom.y >= pVia.y) {
505 if(!leftHandTraffic) {
506 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
507 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
508 } else {
509 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180));
510 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180));
511 }
512 iconAngle = 90-fromAngleDeg;
513 }
514 if(pFrom.x < pVia.x && pFrom.y < pVia.y) {
515 if(!leftHandTraffic) {
516 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90));
517 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90));
518 } else {
519 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90));
520 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90));
521 }
522 iconAngle = 90+fromAngleDeg;
523 }
524 if(pFrom.x >= pVia.x && pFrom.y < pVia.y) {
525 if(!leftHandTraffic) {
526 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180));
527 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180));
528 } else {
529 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
530 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
531 }
532 iconAngle = 270-fromAngleDeg;
533 }
534
535 drawRestriction(inactive || r.isDisabled() ? icon.getDisabledIcon() : icon.icon,
536 pVia, vx, vx2, vy, vy2, iconAngle, r.isSelected());
537 }
538
539 public void drawVirtualNodes(Collection<Way> ways) {
540
541 if (virtualNodeSize != 0) {
542 GeneralPath path = new GeneralPath();
543 for (Way osm: ways){
544 if (osm.isUsable() && !osm.isDisabled()) {
545 visitVirtual(path, osm);
546 }
547 }
548 g.setColor(nodeColor);
549 g.draw(path);
550 }
551 }
552
553 public void visitVirtual(GeneralPath path, Way w) {
554 Iterator<Node> it = w.getNodes().iterator();
555 if (it.hasNext()) {
556 Point lastP = nc.getPoint(it.next());
557 while(it.hasNext())
558 {
559 Point p = nc.getPoint(it.next());
560 if(isSegmentVisible(lastP, p) && isLargeSegment(lastP, p, virtualNodeSpace))
561 {
562 int x = (p.x+lastP.x)/2;
563 int y = (p.y+lastP.y)/2;
564 path.moveTo(x-virtualNodeSize, y);
565 path.lineTo(x+virtualNodeSize, y);
566 path.moveTo(x, y-virtualNodeSize);
567 path.lineTo(x, y+virtualNodeSize);
568 }
569 lastP = p;
570 }
571 }
572 }
573
574 private static boolean isLargeSegment(Point p1, Point p2, int space) {
575 int xd = p1.x-p2.x; if(xd < 0) {
576 xd = -xd;
577 }
578 int yd = p1.y-p2.y; if(yd < 0) {
579 yd = -yd;
580 }
581 return (xd+yd > space);
582 }
583
584 /**
585 * Draw a number of the order of the two consecutive nodes within the
586 * parents way
587 */
588 public void drawOrderNumber(Node n1, Node n2, int orderNumber) {
589 Point p1 = nc.getPoint(n1);
590 Point p2 = nc.getPoint(n2);
591 drawOrderNumber(p1, p2, orderNumber);
592 }
593
594 /**
595 * Draw an number of the order of the two consecutive nodes within the
596 * parents way
597 */
598 protected void drawOrderNumber(Point p1, Point p2, int orderNumber) {
599 if (isSegmentVisible(p1, p2) && isLargeSegment(p1, p2, segmentNumberSpace)) {
600 String on = Integer.toString(orderNumber);
601 int strlen = on.length();
602 int x = (p1.x+p2.x)/2 - 4*strlen;
603 int y = (p1.y+p2.y)/2 + 4;
604
605 if(virtualNodeSize != 0 && isLargeSegment(p1, p2, virtualNodeSpace))
606 {
607 y = (p1.y+p2.y)/2 - virtualNodeSize - 3;
608 }
609
610 Color c = g.getColor();
611 g.setColor(backgroundColor);
612 g.fillRect(x-1, y-12, 8*strlen+1, 14);
613 g.setColor(c);
614 g.drawString(on, x, y);
615 }
616 }
617
618 //TODO Not a good place for this method
619 public String getNodeName(Node n) {
620 String name = null;
621 if (n.hasKeys()) {
622 for (String rn : regionalNameOrder) {
623 name = n.get(rn);
624 if (name != null) {
625 break;
626 }
627 }
628 }
629 return name;
630 }
631
632 //TODO Not a good place for this method
633 public String getAreaName(OsmPrimitive w) {
634 String name = null;
635 if (w.hasKeys()) {
636 for (String rn : regionalNameOrder) {
637 name = w.get(rn);
638 if (name != null) {
639 break;
640 }
641 }
642 }
643 return name;
644 }
645
646 public boolean isInactive() {
647 return inactive;
648 }
649
650 public boolean isShowNames() {
651 return showNames;
652 }
653
654 public double getCircum() {
655 return circum;
656 }
657
658 public boolean isShowIcons() {
659 return showIcons;
660 }
661
662}
Note: See TracBrowser for help on using the repository browser.