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

Last change on this file since 1235 was 1235, checked in by ulfl, 15 years ago

first set of performance optimizations:

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