source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java@ 1240

Last change on this file since 1240 was 1240, checked in by stoecker, 15 years ago

cleanup style handling

  • Property svn:eol-style set to native
File size: 35.0 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.data.osm.visitor;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.BasicStroke;
8import java.awt.Color;
9import java.awt.Font;
10import java.awt.Graphics2D;
11import java.awt.Point;
12import java.awt.Polygon;
13import java.awt.Stroke;
14import java.awt.geom.GeneralPath;
15import java.util.ArrayList;
16import java.util.Collection;
17import java.util.LinkedList;
18import java.util.Locale;
19
20import javax.swing.ImageIcon;
21
22import org.openstreetmap.josm.Main;
23import org.openstreetmap.josm.data.osm.DataSet;
24import org.openstreetmap.josm.data.osm.Node;
25import org.openstreetmap.josm.data.osm.OsmPrimitive;
26import org.openstreetmap.josm.data.osm.Relation;
27import org.openstreetmap.josm.data.osm.RelationMember;
28import org.openstreetmap.josm.data.osm.Way;
29import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
30import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
31import org.openstreetmap.josm.gui.mappaint.ElemStyle;
32import org.openstreetmap.josm.gui.mappaint.ElemStyles;
33import org.openstreetmap.josm.gui.mappaint.IconElemStyle;
34import org.openstreetmap.josm.gui.mappaint.LineElemStyle;
35import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
36
37public class MapPaintVisitor extends SimplePaintVisitor {
38 protected boolean useRealWidth;
39 protected boolean zoomLevelDisplay;
40 protected boolean fillAreas;
41 protected boolean drawMultipolygon;
42 protected int fillAlpha;
43 protected Color untaggedColor;
44 protected Color textColor;
45 protected boolean currentDashed = false;
46 protected int currentWidth = 0;
47 protected Stroke currentStroke = null;
48 protected Font orderFont;
49 protected ElemStyles.StyleSet styles;
50 protected double circum;
51 protected String regionalNameOrder[];
52 protected Boolean selectedCall;
53 protected Collection<OsmPrimitive> alreadyDrawn;
54 protected Collection<Way> alreadyDrawnAreas;
55
56 protected boolean isZoomOk(ElemStyle e) {
57 if (!zoomLevelDisplay) /* show everything if the user wishes so */
58 return true;
59
60 if(e == null) /* the default for things that don't have a rule (show, if scale is smaller than 1500m) */
61 return (circum < 1500);
62
63 // formula to calculate a map scale: natural size / map size = scale
64 // example: 876000mm (876m as displayed) / 22mm (roughly estimated screen size of legend bar) = 39818
65 //
66 // so the exact "correcting value" below depends only on the screen size and resolution
67 // XXX - do we need a Preference setting for this (if things vary widely)?
68 return !(circum >= e.maxScale / 22 || circum < e.minScale / 22);
69 }
70
71 /**
72 * Draw a small rectangle.
73 * White if selected (as always) or red otherwise.
74 *
75 * @param n The node to draw.
76 */
77 public void visit(Node n) {
78 // check, if the node is visible at all
79 Point p = nc.getPoint(n.eastNorth);
80 if ((!selectedCall && n.selected) || (p.x < 0) || (p.y < 0)
81 || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
82
83 IconElemStyle nodeStyle = styles != null ? (IconElemStyle)styles.get(n) : null;
84 if (nodeStyle != null && isZoomOk(nodeStyle))
85 drawNode(n, nodeStyle.icon, nodeStyle.annotate, n.selected);
86 else if (n.selected)
87 drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
88 else if (n.tagged)
89 drawNode(n, nodeColor, taggedNodeSize, taggedNodeRadius, fillUnselectedNode);
90 else
91 drawNode(n, nodeColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode);
92 }
93
94 /**
95 * Draw a line for all segments, according to tags.
96 * @param w The way to draw.
97 */
98 public void visit(Way w) {
99 if(w.nodes.size() < 2 && (!selectedCall && w.selected))
100 return;
101
102 // check, if the way is visible at all
103 Polygon polygon = getPolygon(w);
104 if(!isPolygonVisible(polygon))
105 return;
106
107 ElemStyle wayStyle = styles != null ? styles.get(w) : null;
108
109 if(!isZoomOk(wayStyle))
110 return;
111
112 LineElemStyle l = null;
113 Color areacolor = untaggedColor;
114 if(wayStyle!=null)
115 {
116 if(wayStyle instanceof LineElemStyle)
117 l = (LineElemStyle)wayStyle;
118 else if (wayStyle instanceof AreaElemStyle)
119 {
120 areacolor = ((AreaElemStyle)wayStyle).color;
121 l = ((AreaElemStyle)wayStyle).line;
122 if (fillAreas)
123 drawArea(polygon, w.selected ? selectedColor : areacolor);
124 }
125 }
126
127 drawWay(w, l, areacolor, w.selected);
128 }
129
130 public void drawWay(Way w, LineElemStyle l, Color color, Boolean selected) {
131 // show direction arrows, if draw.segment.relevant_directions_only is not set,
132 // the way is tagged with a direction key
133 // (even if the tag is negated as in oneway=false) or the way is selected
134 boolean showDirection = w.selected || ((!useRealWidth) && (showDirectionArrow
135 && (!showRelevantDirectionsOnly || w.hasDirectionKeys)));
136 int width = defaultSegmentWidth;
137 int realWidth = 0; //the real width of the element in meters
138 boolean dashed = false;
139 Node lastN;
140
141 if(l != null)
142 {
143 color = l.color;
144 width = l.width;
145 realWidth = l.realWidth;
146 dashed = l.dashed;
147 }
148 if(selected)
149 color = selectedColor;
150 if (realWidth > 0 && useRealWidth && !showDirection)
151 {
152 int tmpWidth = (int) (100 / (float) (circum / realWidth));
153 if (tmpWidth > width) width = tmpWidth;
154 }
155 if(w.selected)
156 color = selectedColor;
157
158 // draw overlays under the way
159 if(l != null && l.overlays != null)
160 {
161 for(LineElemStyle s : l.overlays)
162 {
163 if(!s.over)
164 {
165 lastN = null;
166 for(Node n : w.nodes)
167 {
168 if(lastN != null)
169 {
170 drawSeg(lastN, n, s.color != null && !w.selected ? s.color : color,
171 false, s.getWidth(width), s.dashed);
172 }
173 lastN = n;
174 }
175 }
176 }
177 }
178
179 // draw the way
180 lastN = null;
181 for(Node n : w.nodes)
182 {
183 if(lastN != null)
184 drawSeg(lastN, n, color, showDirection, width, dashed);
185 lastN = n;
186 }
187
188 // draw overlays above the way
189 if(l != null && l.overlays != null)
190 {
191 for(LineElemStyle s : l.overlays)
192 {
193 if(s.over)
194 {
195 lastN = null;
196 for(Node n : w.nodes)
197 {
198 if(lastN != null)
199 {
200 drawSeg(lastN, n, s.color != null && !w.selected ? s.color : color,
201 false, s.getWidth(width), s.dashed);
202 }
203 lastN = n;
204 }
205 }
206 }
207 }
208
209 if(showOrderNumber)
210 {
211 int orderNumber = 0;
212 lastN = null;
213 for(Node n : w.nodes)
214 {
215 if(lastN != null)
216 {
217 orderNumber++;
218 drawOrderNumber(lastN, n, orderNumber);
219 }
220 lastN = n;
221 }
222 }
223 displaySegments();
224 }
225
226 public Collection<Way> joinWays(Collection<Way> join, OsmPrimitive errs)
227 {
228 Collection<Way> res = new LinkedList<Way>();
229 Object[] joinArray = join.toArray();
230 int left = join.size();
231 while(left != 0)
232 {
233 Way w = null;
234 Boolean selected = false;
235 ArrayList<Node> n = null;
236 Boolean joined = true;
237 while(joined && left != 0)
238 {
239 joined = false;
240 for(int i = 0; i < joinArray.length && left != 0; ++i)
241 {
242 if(joinArray[i] != null)
243 {
244 Way c = (Way)joinArray[i];
245 if(w == null)
246 { w = c; selected = w.selected; joinArray[i] = null; --left; }
247 else
248 {
249 int mode = 0;
250 int cl = c.nodes.size()-1;
251 int nl;
252 if(n == null)
253 {
254 nl = w.nodes.size()-1;
255 if(w.nodes.get(nl) == c.nodes.get(0)) mode = 21;
256 else if(w.nodes.get(nl) == c.nodes.get(cl)) mode = 22;
257 else if(w.nodes.get(0) == c.nodes.get(0)) mode = 11;
258 else if(w.nodes.get(0) == c.nodes.get(cl)) mode = 12;
259 }
260 else
261 {
262 nl = n.size()-1;
263 if(n.get(nl) == c.nodes.get(0)) mode = 21;
264 else if(n.get(0) == c.nodes.get(cl)) mode = 12;
265 else if(n.get(0) == c.nodes.get(0)) mode = 11;
266 else if(n.get(nl) == c.nodes.get(cl)) mode = 22;
267 }
268 if(mode != 0)
269 {
270 joinArray[i] = null;
271 joined = true;
272 if(c.selected) selected = true;
273 --left;
274 if(n == null) n = new ArrayList(w.nodes);
275 n.remove((mode == 21 || mode == 22) ? nl : 0);
276 if(mode == 21)
277 n.addAll(c.nodes);
278 else if(mode == 12)
279 n.addAll(0, c.nodes);
280 else if(mode == 22)
281 {
282 for(Node node : c.nodes)
283 n.add(nl, node);
284 }
285 else /* mode == 11 */
286 {
287 for(Node node : c.nodes)
288 n.add(0, node);
289 }
290 }
291 }
292 }
293 } /* for(i = ... */
294 } /* while(joined) */
295 if(n != null)
296 {
297 w = new Way(w);
298 w.nodes.clear();
299 w.nodes.addAll(n);
300 w.selected = selected;
301 }
302 if(!w.isClosed())
303 {
304 if(errs != null)
305 {
306 errs.putError(tr("multipolygon way ''{0}'' is not closed.",
307 w.getName()), true);
308 }
309 }
310 res.add(w);
311 } /* while(left != 0) */
312
313 return res;
314 }
315
316 public void drawSelectedRelation(Relation r)
317 {
318 for (RelationMember m : r.members)
319 {
320 if (m.member != null && !m.member.incomplete && !m.member.deleted
321 && !(m.member instanceof Relation))
322 {
323 /* nodes drawn on second call */
324 if(!(m.member instanceof Node))
325 drawSelected(m.member, styles != null ? styles.get(m.member)
326 : null, true, true);
327 alreadyDrawn.add(m.member);
328 }
329 }
330 }
331
332 public void drawSelected(OsmPrimitive osm, ElemStyle style, Boolean area,
333 Boolean areaselected)
334 {
335 if(osm instanceof Way)
336 {
337 if(style instanceof AreaElemStyle)
338 {
339 drawWay((Way)osm, ((AreaElemStyle)style).line, selectedColor, true);
340 if(area)
341 drawArea(getPolygon((Way)osm), areaselected ? selectedColor
342 : ((AreaElemStyle)style).color);
343 }
344 else
345 {
346 drawWay((Way)osm, (LineElemStyle)style, selectedColor, true);
347 }
348 }
349 else if(osm instanceof Node)
350 {
351 if(style != null && isZoomOk(style))
352 drawNode((Node)osm, ((IconElemStyle)style).icon,
353 ((IconElemStyle)style).annotate, true);
354 else
355 drawNode((Node)osm, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
356 }
357 }
358
359 public void visit(Relation r) {
360 // draw multipolygon relations including their ways
361 // other relations are only drawn when selected
362 if(r.selected)
363 {
364 if(selectedCall)
365 {
366 for (RelationMember m : r.members)
367 {
368 /* second call - draw nodes */
369 if (m.member != null && !m.member.incomplete && !m.member.deleted
370 && m.member instanceof Node)
371 {
372 drawSelected(m.member, styles != null ? styles.get(m.member) : null, true, true);
373 alreadyDrawn.add(m.member);
374 }
375 }
376 return;
377 }
378 }
379 if (!drawMultipolygon || r.keys == null || !"multipolygon".equals(r.keys.get("type")))
380 {
381 if(r.selected)
382 drawSelectedRelation(r);
383 return;
384 }
385
386 Collection<Way> inner = new LinkedList<Way>();
387 Collection<Way> outer = new LinkedList<Way>();
388 Collection<Way> innerclosed = new LinkedList<Way>();
389 Collection<Way> outerclosed = new LinkedList<Way>();
390 Boolean incomplete = false;
391
392 r.clearErrors();
393
394 for (RelationMember m : r.members)
395 {
396 if(m.member == null) /* Should not happen, must be a bug elsewhere */
397 r.putError(tr("Empty member in relation."), true);
398 else if(m.member.deleted)
399 r.putError(tr("Deleted member ''{0}'' in relation.",
400 m.member.getName()), true);
401 else if(m.member.incomplete)
402 incomplete = true;
403 else
404 {
405 if(m.member instanceof Way)
406 {
407 Way w = (Way) m.member;
408 if(w.nodes.size() < 2)
409 {
410 r.putError(tr("Way ''{0}'' with less than two points.",
411 w.getName()), true);
412 }
413 else if("inner".equals(m.role))
414 inner.add(w);
415 else if("outer".equals(m.role))
416 outer.add(w);
417 else
418 {
419 r.putError(tr("No useful role ''{0}'' for Way ''{1}''.",
420 m.role == null ? "" : m.role, w.getName()), true);
421 if(m.role == null || m.role.length() == 0)
422 outer.add(w);
423 else if(r.selected)
424 drawSelected(m.member, styles != null ? styles.get(m.member) : null, true, true);
425 }
426 }
427 else
428 {
429 /* nodes drawn on second call */
430 r.putError(tr("Non-Way ''{0}'' in multipolygon.",
431 m.member.getName()), true);
432 }
433 }
434 }
435
436 ElemStyle wayStyle = styles != null ? styles.get(r) : null;
437 /* find one wayStyle, prefer the style from Relation or take the first
438 one of outer rings */
439 if(styles != null && (wayStyle == null || !(wayStyle instanceof AreaElemStyle)))
440 {
441 for (Way w : outer)
442 {
443 if(wayStyle == null || !(wayStyle instanceof AreaElemStyle))
444 wayStyle = styles.get(w);
445 }
446 }
447
448 if(wayStyle != null && wayStyle instanceof AreaElemStyle)
449 {
450 Boolean zoomok = isZoomOk(wayStyle);
451 Collection<Way> join = new LinkedList<Way>();
452
453 /* parse all outer rings and join them */
454 for (Way w : outer)
455 {
456 if(w.isClosed()) outerclosed.add(w);
457 else join.add(w);
458 }
459 if(join.size() != 0)
460 {
461 for(Way w : joinWays(join, incomplete ? null : r))
462 outerclosed.add(w);
463 }
464
465 /* parse all inner rings and join them */
466 join.clear();
467 for (Way w : inner)
468 {
469 if(w.isClosed()) innerclosed.add(w);
470 else join.add(w);
471 }
472 if(join.size() != 0)
473 {
474 for(Way w : joinWays(join, incomplete ? null : r))
475 innerclosed.add(w);
476 }
477
478 if(outerclosed.size() == 0)
479 {
480 r.putError(tr("No outer way for multipolygon ''{0}''.",
481 r.getName()), true);
482 }
483 else if(zoomok) /* draw */
484 {
485 class PolyData {
486 public Polygon poly = new Polygon();
487 public Way way;
488 private Point p = null;
489 private Collection<Polygon> inner = null;
490 PolyData(Way w)
491 {
492 way = w;
493 for (Node n : w.nodes)
494 {
495 p = nc.getPoint(n.eastNorth);
496 poly.addPoint(p.x,p.y);
497 }
498 }
499 public int contains(Polygon p)
500 {
501 int contains = p.npoints;
502 for(int i = 0; i < p.npoints; ++i)
503 {
504 if(poly.contains(p.xpoints[i],p.ypoints[i]))
505 --contains;
506 }
507 if(contains == 0) return 1; /* inside */
508 if(contains == p.npoints) return 0; /* outside */
509 return 2; /* mixed */
510 }
511 public void addInner(Polygon p)
512 {
513 if(inner == null)
514 inner = new ArrayList<Polygon>();
515 inner.add(p);
516 }
517 public Polygon get()
518 {
519 if(inner != null)
520 {
521 for (Polygon pp : inner)
522 {
523 for(int i = 0; i < pp.npoints; ++i)
524 poly.addPoint(pp.xpoints[i],pp.ypoints[i]);
525 poly.addPoint(p.x,p.y);
526 }
527 inner = null;
528 }
529 return poly;
530 }
531 }
532 LinkedList<PolyData> poly = new LinkedList<PolyData>();
533 for (Way w : outerclosed)
534 {
535 poly.add(new PolyData(w));
536 }
537 for (Way wInner : innerclosed)
538 {
539 Polygon polygon = new Polygon();
540
541 for (Node n : wInner.nodes)
542 {
543 Point pInner = nc.getPoint(n.eastNorth);
544 polygon.addPoint(pInner.x,pInner.y);
545 }
546 if(!wInner.isClosed())
547 {
548 Point pInner = nc.getPoint(wInner.nodes.get(0).eastNorth);
549 polygon.addPoint(pInner.x,pInner.y);
550 }
551 PolyData o = null;
552 for (PolyData pd : poly)
553 {
554 Integer c = pd.contains(polygon);
555 if(c >= 1)
556 {
557 if(c > 1 && pd.way.isClosed())
558 {
559 r.putError(tr("Intersection between ways ''{0}'' and ''{1}''.",
560 pd.way.getName(), wInner.getName()), true);
561 }
562 if(o == null || o.contains(pd.poly) > 0)
563 o = pd;
564 }
565 }
566 if(o == null)
567 {
568 if(!incomplete)
569 {
570 r.putError(tr("Inner way ''{0}'' is outside.",
571 wInner.getName()), true);
572 }
573 o = poly.get(0);
574 }
575 o.addInner(polygon);
576 }
577 for (PolyData pd : poly)
578 {
579 drawArea(pd.get(), (pd.way.selected || r.selected) ? selectedColor
580 : ((AreaElemStyle)wayStyle).color);
581 }
582 }
583 for (Way wInner : inner)
584 {
585 ElemStyle innerStyle = styles.get(wInner);
586 if(innerStyle == null)
587 {
588 if(zoomok)
589 {
590 drawWay(wInner, ((AreaElemStyle)wayStyle).line,
591 ((AreaElemStyle)wayStyle).color, wInner.selected
592 || r.selected);
593 }
594 alreadyDrawn.add(wInner);
595 }
596 else
597 {
598 if(r.selected)
599 {
600 drawSelected(wInner, innerStyle,
601 !wayStyle.equals(innerStyle), wInner.selected);
602 alreadyDrawn.add(wInner);
603 }
604 if(wayStyle.equals(innerStyle))
605 {
606 r.putError(tr("Style for inner way ''{0}'' equals multipolygon.",
607 wInner.getName()), false);
608 if(!r.selected)
609 alreadyDrawnAreas.add(wInner);
610 }
611 }
612 }
613 for (Way wOuter : outer)
614 {
615 ElemStyle outerStyle = styles.get(wOuter);
616 if(outerStyle == null)
617 {
618 if(zoomok)
619 {
620 drawWay(wOuter, ((AreaElemStyle)wayStyle).line,
621 ((AreaElemStyle)wayStyle).color, wOuter.selected
622 || r.selected);
623 }
624 alreadyDrawn.add(wOuter);
625 }
626 else
627 {
628 if(outerStyle instanceof AreaElemStyle
629 && !wayStyle.equals(outerStyle))
630 {
631 r.putError(tr("Style for outer way ''{0}'' mismatches.",
632 wOuter.getName()), true);
633 }
634 if(r.selected)
635 {
636 drawSelected(wOuter, outerStyle, false, false);
637 alreadyDrawn.add(wOuter);
638 }
639// else if(outerStyle instanceof AreaElemStyle)
640 alreadyDrawnAreas.add(wOuter);
641 }
642 }
643 }
644 else if(r.selected)
645 drawSelectedRelation(r);
646 }
647
648 protected Polygon getPolygon(Way w)
649 {
650 Polygon polygon = new Polygon();
651
652 for (Node n : w.nodes)
653 {
654 Point p = nc.getPoint(n.eastNorth);
655 polygon.addPoint(p.x,p.y);
656 }
657 return polygon;
658 }
659
660 protected void drawArea(Polygon polygon, Color color)
661 {
662 // set the opacity (alpha) level of the filled polygon
663 g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
664 g.fillPolygon(polygon);
665 }
666
667 protected void drawNode(Node n, ImageIcon icon, boolean annotate, Boolean selected) {
668 Point p = nc.getPoint(n.eastNorth);
669 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
670 int w = icon.getIconWidth(), h=icon.getIconHeight();
671 icon.paintIcon ( Main.map.mapView, g, p.x-w/2, p.y-h/2 );
672 String name = getNodeName(n);
673 if (name!=null && annotate)
674 {
675 g.setColor(textColor);
676 Font defaultFont = g.getFont();
677 g.setFont (orderFont);
678 g.drawString (name, p.x+w/2+2, p.y+h/2+2);
679 g.setFont(defaultFont);
680 }
681 if (selected)
682 {
683 g.setColor ( selectedColor );
684 g.drawRect (p.x-w/2-2,p.y-w/2-2, w+4, h+4);
685 }
686 }
687
688 protected String getNodeName(Node n) {
689 String name = null;
690 if (n.keys != null) {
691 for (int i = 0; i < regionalNameOrder.length; i++) {
692 name = n.keys.get(regionalNameOrder[i]);
693 if (name != null) break;
694 }
695 }
696 return name;
697 }
698
699 private void drawSeg(Node n1, Node n2, Color col, boolean showDirection, int width, boolean dashed) {
700 if (col != currentColor || width != currentWidth || dashed != currentDashed) {
701 displaySegments(col, width, dashed);
702 }
703 Point p1 = nc.getPoint(n1.eastNorth);
704 Point p2 = nc.getPoint(n2.eastNorth);
705
706 if (!isSegmentVisible(p1, p2)) {
707 return;
708 }
709 currentPath.moveTo(p1.x, p1.y);
710 currentPath.lineTo(p2.x, p2.y);
711
712 if (showDirection) {
713 double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
714 currentPath.lineTo((int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
715 currentPath.moveTo((int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
716 currentPath.lineTo(p2.x, p2.y);
717 }
718 }
719
720 protected void displaySegments() {
721 displaySegments(null, 0, false);
722 }
723
724 protected void displaySegments(Color newColor, int newWidth, boolean newDash) {
725 if (currentPath != null) {
726 Graphics2D g2d = (Graphics2D)g;
727 g2d.setColor(inactive ? inactiveColor : currentColor);
728 if (currentStroke == null) {
729 if (currentDashed)
730 g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,new float[] {9},0));
731 else
732 g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
733 }
734 g2d.draw(currentPath);
735 g2d.setStroke(new BasicStroke(1));
736
737 currentPath = new GeneralPath();
738 currentColor = newColor;
739 currentWidth = newWidth;
740 currentDashed = newDash;
741 currentStroke = null;
742 }
743 }
744
745 /**
746 * Draw the node as small rectangle with the given color.
747 *
748 * @param n The node to draw.
749 * @param color The color of the node.
750 */
751 public void drawNode(Node n, Color color, int size, int radius, boolean fill) {
752 if (isZoomOk(null) && size > 1) {
753 Point p = nc.getPoint(n.eastNorth);
754 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth())
755 || (p.y > nc.getHeight()))
756 return;
757 g.setColor(color);
758 if (fill) {
759 g.fillRect(p.x - radius, p.y - radius, size, size);
760 g.drawRect(p.x - radius, p.y - radius, size, size);
761 } else
762 g.drawRect(p.x - radius, p.y - radius, size, size);
763
764 String name = getNodeName(n);
765 if (name!=null /* && annotate */)
766 {
767 g.setColor(textColor);
768 Font defaultFont = g.getFont();
769 g.setFont (orderFont);
770 g.drawString (name, p.x+radius+2, p.y+radius+2);
771 g.setFont(defaultFont);
772 }
773 }
774 }
775
776 public void getColors()
777 {
778 super.getColors();
779 untaggedColor = Main.pref.getColor(marktr("untagged"),Color.GRAY);
780 textColor = Main.pref.getColor (marktr("text"), Color.WHITE);
781 }
782
783 // Shows areas before non-areas
784 public void visitAll(DataSet data, Boolean virtual) {
785
786 boolean profiler = Main.pref.getBoolean("mappaint.profiler",false);
787 long profilerStart = java.lang.System.currentTimeMillis();
788 long profilerLast = profilerStart;
789 int profilerN;
790 if(profiler)
791 {
792 System.out.println("Mappaint Profiler");
793 }
794
795 getSettings(virtual);
796 useRealWidth = Main.pref.getBoolean("mappaint.useRealWidth",false);
797 zoomLevelDisplay = Main.pref.getBoolean("mappaint.zoomLevelDisplay",false);
798 fillAreas = Main.pref.getBoolean("mappaint.fillareas", true);
799 fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref.getInteger("mappaint.fillalpha", 50))));
800 circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; // circumference of the earth in meter
801 styles = MapPaintStyles.getStyles().getStyleSet();
802 drawMultipolygon = Main.pref.getBoolean("mappaint.multipolygon",false);
803 orderFont = new Font(Main.pref.get("mappaint.font","Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8));
804 String currentLocale = Locale.getDefault().getLanguage();
805 regionalNameOrder = Main.pref.get("mappaint.nameOrder", "name:"+currentLocale+";name;int_name;ref;operator;brand").split(";");
806
807 alreadyDrawn = new LinkedList<OsmPrimitive>();
808 alreadyDrawnAreas = new LinkedList<Way>();
809 selectedCall = false;
810
811 if(profiler)
812 {
813 System.out.format("Prepare : %4dms\n", (java.lang.System.currentTimeMillis()-profilerLast));
814 profilerLast = java.lang.System.currentTimeMillis();
815 }
816
817 if (fillAreas && styles != null && styles.hasAreas()) {
818 Collection<Way> noAreaWays = new LinkedList<Way>();
819
820 /*** RELATIONS ***/
821 profilerN = 0;
822 for (final Relation osm : data.relations)
823 {
824 if(!osm.deleted && !osm.incomplete)
825 {
826 osm.visit(this);
827 profilerN++;
828 }
829 }
830
831 if(profiler)
832 {
833 System.out.format("Relations: %4dms, n=%d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
834 profilerLast = java.lang.System.currentTimeMillis();
835 }
836
837 /*** AREAS ***/
838 profilerN = 0;
839 for (final Way osm : data.ways)
840 {
841 if (!osm.incomplete && !osm.deleted && !alreadyDrawn.contains(osm))
842 {
843 if(styles.isArea((Way)osm) && !alreadyDrawnAreas.contains(osm))
844 {
845 osm.visit(this);
846 profilerN++;
847 } else
848 noAreaWays.add((Way)osm);
849 }
850 }
851 alreadyDrawnAreas = null;
852
853 if(profiler)
854 {
855 System.out.format("Areas : %4dms, n=%d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
856 profilerLast = java.lang.System.currentTimeMillis();
857 }
858
859 /*** WAYS ***/
860 profilerN = 0;
861 fillAreas = false;
862 for (final OsmPrimitive osm : noAreaWays)
863 {
864 osm.visit(this);
865 profilerN++;
866 }
867
868 if(profiler)
869 {
870 System.out.format("Ways : %4dms, n=%d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
871 profilerLast = java.lang.System.currentTimeMillis();
872 }
873 }
874 else
875 {
876 /*** WAYS (filling disabled) ***/
877 profilerN = 0;
878 for (final OsmPrimitive osm : data.ways)
879 if (!osm.incomplete && !osm.deleted && !osm.selected)
880 {
881 osm.visit(this);
882 profilerN++;
883 }
884
885 if(profiler)
886 {
887 System.out.format("Ways : %4dms, n=%d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
888 profilerLast = java.lang.System.currentTimeMillis();
889 }
890 }
891
892 /*** SELECTED ***/
893 selectedCall = true;
894 profilerN = 0;
895 for (final OsmPrimitive osm : data.getSelected()) {
896 if (!osm.incomplete && !osm.deleted
897 && !(osm instanceof Node) && !alreadyDrawn.contains(osm))
898 {
899 osm.visit(this);
900 profilerN++;
901 }
902 }
903
904 if(profiler)
905 {
906 System.out.format("Selected : %4dms, n=%d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
907 profilerLast = java.lang.System.currentTimeMillis();
908 }
909
910 /*** DISPLAY CACHED SEGMENTS (WAYS) NOW ***/
911 displaySegments();
912 /*System.out.println("display segments " + (java.lang.System.currentTimeMillis()-profilerLast) + "ms");
913 profilerLast = java.lang.System.currentTimeMillis();*/
914
915 /*** NODES ***/
916 profilerN = 0;
917 for (final OsmPrimitive osm : data.nodes)
918 if (!osm.incomplete && !osm.deleted && !alreadyDrawn.contains(osm))
919 {
920 osm.visit(this);
921 profilerN++;
922 }
923
924 if(profiler)
925 {
926 System.out.format("Nodes : %4dms, n=%d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
927 profilerLast = java.lang.System.currentTimeMillis();
928 }
929
930 alreadyDrawn = null;
931
932 /*** VIRTUAL ***/
933 if (virtualNodeSize != 0)
934 {
935 profilerN = 0;
936 currentColor = nodeColor;
937 for (final OsmPrimitive osm : data.ways)
938 if (!osm.incomplete && !osm.deleted)
939 {
940 visitVirtual((Way)osm);
941 profilerN++;
942 }
943
944 if(profiler)
945 {
946 System.out.format("Virtual : %4dms, n=%d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
947 profilerLast = java.lang.System.currentTimeMillis();
948 }
949
950 displaySegments(null);
951 /*System.out.println("display segments virtual " + (java.lang.System.currentTimeMillis()-profilerLast) + "ms");
952 profilerLast = java.lang.System.currentTimeMillis();*/
953 }
954
955 if(profiler)
956 {
957 System.out.format("All : %4dms\n", (profilerLast-profilerStart));
958 }
959 }
960
961 /**
962 * Draw a number of the order of the two consecutive nodes within the
963 * parents way
964 */
965 protected void drawOrderNumber(Node n1, Node n2, int orderNumber) {
966 Point p1 = nc.getPoint(n1.eastNorth);
967 Point p2 = nc.getPoint(n2.eastNorth);
968 drawOrderNumber(p1, p2, orderNumber);
969 }
970}
Note: See TracBrowser for help on using the repository browser.