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

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

fix #2174 patch by xeen

  • Property svn:eol-style set to native
File size: 52.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.Image;
12import java.awt.Point;
13import java.awt.Polygon;
14import java.awt.Stroke;
15import java.awt.geom.GeneralPath;
16import java.util.ArrayList;
17import java.util.Collection;
18import java.util.LinkedList;
19import java.util.Locale;
20import java.util.Iterator;
21
22import javax.swing.ImageIcon;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.data.osm.DataSet;
26import org.openstreetmap.josm.data.osm.Node;
27import org.openstreetmap.josm.data.osm.OsmPrimitive;
28import org.openstreetmap.josm.data.osm.Relation;
29import org.openstreetmap.josm.data.osm.RelationMember;
30import org.openstreetmap.josm.data.osm.Way;
31import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
32import org.openstreetmap.josm.data.coor.LatLon;
33import org.openstreetmap.josm.data.coor.EastNorth;
34import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
35import org.openstreetmap.josm.gui.mappaint.ElemStyle;
36import org.openstreetmap.josm.gui.mappaint.ElemStyles;
37import org.openstreetmap.josm.gui.mappaint.IconElemStyle;
38import org.openstreetmap.josm.gui.mappaint.LineElemStyle;
39import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
40import org.openstreetmap.josm.tools.ImageProvider;
41
42public class MapPaintVisitor extends SimplePaintVisitor {
43 protected boolean useRealWidth;
44 protected boolean zoomLevelDisplay;
45 protected int fillAreas;
46 protected boolean drawMultipolygon;
47 protected boolean drawRestriction;
48 protected boolean leftHandTraffic;
49 protected boolean restrictionDebug;
50 protected int showNames;
51 protected int showIcons;
52 protected int useStrokes;
53 protected int fillAlpha;
54 protected Color untaggedColor;
55 protected Color textColor;
56 protected int currentDashed = 0;
57 protected Color currentDashedColor;
58 protected int currentWidth = 0;
59 protected Stroke currentStroke = null;
60 protected Font orderFont;
61 protected ElemStyles.StyleSet styles;
62 protected double circum;
63 protected double dist;
64 protected String regionalNameOrder[];
65 protected Boolean selectedCall;
66 protected Boolean useStyleCache;
67 private static int paintid = 0;
68 private static int viewid = 0;
69 private EastNorth minEN;
70 private EastNorth maxEN;
71
72 protected int profilerVisibleNodes;
73 protected int profilerVisibleWays;
74 protected int profilerVisibleAreas;
75 protected int profilerSegments;
76 protected int profilerVisibleSegments;
77 protected boolean profilerOmitDraw;
78
79 protected boolean isZoomOk(ElemStyle e) {
80 if (!zoomLevelDisplay) /* show everything if the user wishes so */
81 return true;
82
83 if(e == null) /* the default for things that don't have a rule (show, if scale is smaller than 1500m) */
84 return (circum < 1500);
85
86 // formula to calculate a map scale: natural size / map size = scale
87 // example: 876000mm (876m as displayed) / 22mm (roughly estimated screen size of legend bar) = 39818
88 //
89 // so the exact "correcting value" below depends only on the screen size and resolution
90 // XXX - do we need a Preference setting for this (if things vary widely)?
91 return !(circum >= e.maxScale / 22 || circum < e.minScale / 22);
92 }
93
94 public ElemStyle getPrimitiveStyle(OsmPrimitive osm) {
95 if(!useStyleCache)
96 return (styles != null) ? styles.get(osm) : null;
97
98 if(osm.mappaintStyle == null && styles != null) {
99 osm.mappaintStyle = styles.get(osm);
100 if(osm instanceof Way)
101 ((Way)osm).isMappaintArea = styles.isArea(osm);
102 }
103 return osm.mappaintStyle;
104 }
105
106 public IconElemStyle getPrimitiveNodeStyle(OsmPrimitive osm) {
107 if(!useStyleCache)
108 return (styles != null) ? styles.getIcon(osm) : null;
109
110 if(osm.mappaintStyle == null && styles != null)
111 osm.mappaintStyle = styles.getIcon(osm);
112
113 return (IconElemStyle)osm.mappaintStyle;
114 }
115
116 public boolean isPrimitiveArea(Way osm) {
117 if(!useStyleCache)
118 return styles.isArea(osm);
119
120 if(osm.mappaintStyle == null && styles != null) {
121 osm.mappaintStyle = styles.get(osm);
122 osm.isMappaintArea = styles.isArea(osm);
123 }
124 return osm.isMappaintArea;
125 }
126
127 /**
128 * Draw a small rectangle.
129 * White if selected (as always) or red otherwise.
130 *
131 * @param n The node to draw.
132 */
133 public void visit(Node n) {
134 // check, if the node is visible at all
135 if((n.eastNorth.east() > maxEN.east() ) ||
136 (n.eastNorth.north() > maxEN.north()) ||
137 (n.eastNorth.east() < minEN.east() ) ||
138 (n.eastNorth.north() < minEN.north()))
139 {
140 n.mappaintVisibleCode = viewid;
141 return;
142 }
143 n.mappaintVisibleCode = 0;
144
145 IconElemStyle nodeStyle = (IconElemStyle)getPrimitiveStyle(n);
146
147 if(profilerOmitDraw)
148 return;
149
150 if (nodeStyle != null && isZoomOk(nodeStyle) && showIcons > dist)
151 drawNode(n, nodeStyle.icon, nodeStyle.annotate, n.selected);
152 else if (n.highlighted)
153 drawNode(n, highlightColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
154 else if (n.selected)
155 drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
156 else if (n.tagged)
157 drawNode(n, nodeColor, taggedNodeSize, taggedNodeRadius, fillUnselectedNode);
158 else
159 drawNode(n, nodeColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode);
160 }
161
162 /**
163 * Draw a line for all segments, according to tags.
164 * @param w The way to draw.
165 */
166 public void visit(Way w) {
167 if(w.nodes.size() < 2)
168 {
169 w.mappaintVisibleCode = viewid;
170 return;
171 }
172
173 // check, if the way is visible at all
174 double minx = 10000;
175 double maxx = -10000;
176 double miny = 10000;
177 double maxy = -10000;
178
179 for (Node n : w.nodes)
180 {
181 if(n.eastNorth.east() > maxx) maxx = n.eastNorth.east();
182 if(n.eastNorth.north() > maxy) maxy = n.eastNorth.north();
183 if(n.eastNorth.east() < minx) minx = n.eastNorth.east();
184 if(n.eastNorth.north() < miny) miny = n.eastNorth.north();
185 }
186
187 if ((minx > maxEN.east()) ||
188 (miny > maxEN.north()) ||
189 (maxx < minEN.east()) ||
190 (maxy < minEN.north()))
191 {
192 w.mappaintVisibleCode = viewid;
193 return;
194 }
195
196 ElemStyle wayStyle = getPrimitiveStyle(w);
197
198 if(!isZoomOk(wayStyle))
199 {
200 w.mappaintVisibleCode = viewid;
201 return;
202 }
203
204 w.mappaintVisibleCode = 0;
205 if(fillAreas > dist)
206 w.clearErrors();
207
208 if(wayStyle==null)
209 {
210 // way without style
211 profilerVisibleWays++;
212 if(!profilerOmitDraw)
213 drawWay(w, null, untaggedColor, w.selected);
214 }
215 else if(wayStyle instanceof LineElemStyle)
216 {
217 // way with line style
218 profilerVisibleWays++;
219 if(!profilerOmitDraw)
220 drawWay(w, (LineElemStyle)wayStyle, untaggedColor, w.selected);
221 }
222 else if (wayStyle instanceof AreaElemStyle)
223 {
224 // way with area style
225 if(!profilerOmitDraw)
226 {
227 if (fillAreas > dist)
228 {
229 profilerVisibleAreas++;
230 drawArea(w, w.selected ? selectedColor : ((AreaElemStyle)wayStyle).color);
231 if(!w.isClosed())
232 w.putError(tr("Area style way is not closed."), true);
233 }
234 drawWay(w, ((AreaElemStyle)wayStyle).line, ((AreaElemStyle)wayStyle).color, w.selected);
235 }
236 }
237 }
238
239 public void drawWay(Way w, LineElemStyle l, Color color, Boolean selected) {
240 // show direction arrows, if draw.segment.relevant_directions_only is not set,
241 // the way is tagged with a direction key
242 // (even if the tag is negated as in oneway=false) or the way is selected
243 boolean showDirection = w.selected || ((!useRealWidth) && (showDirectionArrow
244 && (!showRelevantDirectionsOnly || w.hasDirectionKeys)));
245 // head only takes over control if the option is true,
246 // the direction should be shown at all and not only because it's selected
247 boolean showOnlyHeadArrowOnly = showDirection && !w.selected && showHeadArrowOnly;
248 int width = defaultSegmentWidth;
249 int realWidth = 0; //the real width of the element in meters
250 int dashed = 0;
251 Color dashedColor = null;
252 Node lastN;
253
254 if(l != null)
255 {
256 color = l.color;
257 width = l.width;
258 realWidth = l.realWidth;
259 dashed = l.dashed;
260 dashedColor = l.dashedColor;
261 }
262 if(selected)
263 color = selectedColor;
264 if (realWidth > 0 && useRealWidth && !showDirection)
265 {
266 int tmpWidth = (int) (100 / (float) (circum / realWidth));
267 if (tmpWidth > width) width = tmpWidth;
268 }
269
270 if(w.highlighted)
271 color = highlightColor;
272 else if(w.selected)
273 color = selectedColor;
274
275 // draw overlays under the way
276 if(l != null && l.overlays != null)
277 {
278 for(LineElemStyle s : l.overlays)
279 {
280 if(!s.over)
281 {
282 lastN = null;
283 for(Node n : w.nodes)
284 {
285 if(lastN != null)
286 {
287 drawSeg(lastN, n, s.color != null && !w.selected ? s.color : color,
288 false, s.getWidth(width), s.dashed, s.dashedColor);
289 }
290 lastN = n;
291 }
292 }
293 }
294 }
295
296 // draw the way
297 lastN = null;
298 Iterator<Node> it = w.nodes.iterator();
299 while (it.hasNext())
300 {
301 Node n = it.next();
302 if(lastN != null)
303 drawSeg(lastN, n, color,
304 showOnlyHeadArrowOnly ? !it.hasNext() : showDirection, width, dashed, dashedColor);
305 lastN = n;
306 }
307
308 // draw overlays above the way
309 if(l != null && l.overlays != null)
310 {
311 for(LineElemStyle s : l.overlays)
312 {
313 if(s.over)
314 {
315 lastN = null;
316 for(Node n : w.nodes)
317 {
318 if(lastN != null)
319 {
320 drawSeg(lastN, n, s.color != null && !w.selected ? s.color : color,
321 false, s.getWidth(width), s.dashed, s.dashedColor);
322 }
323 lastN = n;
324 }
325 }
326 }
327 }
328
329 if(showOrderNumber)
330 {
331 int orderNumber = 0;
332 lastN = null;
333 for(Node n : w.nodes)
334 {
335 if(lastN != null)
336 {
337 orderNumber++;
338 drawOrderNumber(lastN, n, orderNumber);
339 }
340 lastN = n;
341 }
342 }
343 displaySegments();
344 }
345
346 public Collection<Way> joinWays(Collection<Way> join, OsmPrimitive errs)
347 {
348 Collection<Way> res = new LinkedList<Way>();
349 Object[] joinArray = join.toArray();
350 int left = join.size();
351 while(left != 0)
352 {
353 Way w = null;
354 Boolean selected = false;
355 ArrayList<Node> n = null;
356 Boolean joined = true;
357 while(joined && left != 0)
358 {
359 joined = false;
360 for(int i = 0; i < joinArray.length && left != 0; ++i)
361 {
362 if(joinArray[i] != null)
363 {
364 Way c = (Way)joinArray[i];
365 if(w == null)
366 { w = c; selected = w.selected; joinArray[i] = null; --left; }
367 else
368 {
369 int mode = 0;
370 int cl = c.nodes.size()-1;
371 int nl;
372 if(n == null)
373 {
374 nl = w.nodes.size()-1;
375 if(w.nodes.get(nl) == c.nodes.get(0)) mode = 21;
376 else if(w.nodes.get(nl) == c.nodes.get(cl)) mode = 22;
377 else if(w.nodes.get(0) == c.nodes.get(0)) mode = 11;
378 else if(w.nodes.get(0) == c.nodes.get(cl)) mode = 12;
379 }
380 else
381 {
382 nl = n.size()-1;
383 if(n.get(nl) == c.nodes.get(0)) mode = 21;
384 else if(n.get(0) == c.nodes.get(cl)) mode = 12;
385 else if(n.get(0) == c.nodes.get(0)) mode = 11;
386 else if(n.get(nl) == c.nodes.get(cl)) mode = 22;
387 }
388 if(mode != 0)
389 {
390 joinArray[i] = null;
391 joined = true;
392 if(c.selected) selected = true;
393 --left;
394 if(n == null) n = new ArrayList(w.nodes);
395 n.remove((mode == 21 || mode == 22) ? nl : 0);
396 if(mode == 21)
397 n.addAll(c.nodes);
398 else if(mode == 12)
399 n.addAll(0, c.nodes);
400 else if(mode == 22)
401 {
402 for(Node node : c.nodes)
403 n.add(nl, node);
404 }
405 else /* mode == 11 */
406 {
407 for(Node node : c.nodes)
408 n.add(0, node);
409 }
410 }
411 }
412 }
413 } /* for(i = ... */
414 } /* while(joined) */
415 if(n != null)
416 {
417 w = new Way(w);
418 w.nodes.clear();
419 w.nodes.addAll(n);
420 w.selected = selected;
421 }
422 if(!w.isClosed())
423 {
424 if(errs != null)
425 {
426 errs.putError(tr("multipolygon way ''{0}'' is not closed.",
427 w.getName()), true);
428 }
429 }
430 res.add(w);
431 } /* while(left != 0) */
432
433 return res;
434 }
435
436 public void drawSelectedMember(OsmPrimitive osm, ElemStyle style, Boolean area,
437 Boolean areaselected)
438 {
439 if(osm instanceof Way)
440 {
441 if(style instanceof AreaElemStyle)
442 {
443 drawWay((Way)osm, ((AreaElemStyle)style).line, selectedColor, true);
444 if(area)
445 drawArea((Way)osm, areaselected ? selectedColor
446 : ((AreaElemStyle)style).color);
447 }
448 else
449 {
450 drawWay((Way)osm, (LineElemStyle)style, selectedColor, true);
451 }
452 }
453 else if(osm instanceof Node)
454 {
455 if(style != null && isZoomOk(style))
456 drawNode((Node)osm, ((IconElemStyle)style).icon,
457 ((IconElemStyle)style).annotate, true);
458 else
459 drawNode((Node)osm, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
460 }
461 osm.mappaintDrawnCode = paintid;
462 }
463
464 public void visit(Relation r) {
465
466 r.mappaintVisibleCode = 0;
467
468 // TODO: is it possible to do this like the nodes/ways code?
469 if(profilerOmitDraw)
470 return;
471
472 if(selectedCall)
473 {
474 for (RelationMember m : r.members)
475 {
476 if (m.member != null && !m.member.incomplete && !m.member.deleted
477 && m.member instanceof Node)
478 {
479 drawSelectedMember(m.member, styles != null ? getPrimitiveStyle(m.member) : null, true, true);
480 }
481 }
482 return;
483 }
484 else if (drawMultipolygon && r.keys != null && "multipolygon".equals(r.keys.get("type")))
485 {
486 if(drawMultipolygon(r))
487 return;
488 }
489 else if (drawRestriction && r.keys != null && "restriction".equals(r.keys.get("type")))
490 {
491 drawRestriction(r);
492 }
493
494 if(r.selected) /* draw ways*/
495 {
496 for (RelationMember m : r.members)
497 {
498 if (m.member != null && !m.member.incomplete && !m.member.deleted
499 && m.member instanceof Way) /* nodes drawn on second call */
500 {
501 drawSelectedMember(m.member, styles != null ? getPrimitiveStyle(m.member)
502 : null, true, true);
503 }
504 }
505 }
506 }
507
508 // this current experimental implementation will only work for standard restrictions:
509 // from(Way) / via(Node) / to(Way)
510 public void drawRestriction(Relation r) {
511 if(restrictionDebug)
512 System.out.println("Restriction: " + r.keys.get("name") + " restriction " + r.keys.get("restriction"));
513
514 r.clearErrors();
515
516 Way fromWay = null;
517 Way toWay = null;
518 Node via = null;
519
520 // find the "from", "via" and "to" elements
521 for (RelationMember m : r.members)
522 {
523 if(restrictionDebug)
524 System.out.println("member " + m.member + " selected " + r.selected);
525
526 if(m.member == null)
527 r.putError(tr("Empty member in relation."), true);
528 else if(m.member.deleted)
529 r.putError(tr("Deleted member ''{0}'' in relation.",
530 m.member.getName()), true);
531 else if(m.member.incomplete)
532 {
533 return;
534 }
535 else
536 {
537 if(m.member instanceof Way)
538 {
539 Way w = (Way) m.member;
540 ElemStyle style = getPrimitiveStyle(w);
541 //if(r.selected) {
542 // drawWay(w, null /*(LineElemStyle)style*/, selectedColor, true);
543 // w.mappaintDrawnCode = paintid;
544 //}
545 if(w.nodes.size() < 2)
546 {
547 r.putError(tr("Way ''{0}'' with less than two points.",
548 w.getName()), true);
549 }
550 else if("from".equals(m.role)) {
551 if(fromWay != null)
552 r.putError(tr("More than one \"from\" way found."), true);
553 else {
554 fromWay = w;
555 }
556 } else if("to".equals(m.role)) {
557 if(toWay != null)
558 r.putError(tr("More than one \"to\" way found."), true);
559 else {
560 toWay = w;
561 }
562 }
563 else
564 r.putError(tr("Unknown role ''{0}''.", m.role), true);
565 }
566 else if(m.member instanceof Node)
567 {
568 Node n = (Node) m.member;
569 if("via".equals(m.role))
570 if(via != null)
571 System.out.println("More than one \"via\" found.");
572 else {
573 via = n;
574 }
575 else
576 r.putError(tr("Unknown role ''{0}''.", m.role), true);
577 }
578 else
579 r.putError(tr("Unknown member type for ''{0}''.", m.member.getName()), true);
580 }
581 }
582
583 if (fromWay == null) {
584 r.putError(tr("No \"from\" way found."), true);
585 return;
586 }
587 if (toWay == null) {
588 r.putError(tr("No \"to\" way found."), true);
589 return;
590 }
591 if (via == null) {
592 r.putError(tr("No \"via\" node found."), true);
593 return;
594 }
595
596 // check if "from" way starts or ends at via
597 if(fromWay.nodes.get(0) != via && fromWay.nodes.get(fromWay.nodes.size()-1) != via) {
598 r.putError(tr("The \"from\" way doesn't start or end at a \"via\" node."), true);
599 return;
600 }
601 // check if "to" way starts or ends at via
602 /*if(toWay.nodes.get(0) != via && toWay.nodes.get(toWay.nodes.size()-1) != via) {
603 r.putError(tr("to way doesn't start or end at a via node"), true);
604 //return;
605 }*/
606
607 // find the "direct" nodes before the via node
608 Node fromNode = null;
609 try
610 {
611 if(fromWay.nodes.get(0) == via) {
612 //System.out.println("From way heading away from via");
613 fromNode = fromWay.nodes.get(1);
614 } else {
615 //System.out.println("From way heading towards via");
616 fromNode = fromWay.nodes.get(fromWay.nodes.size()-2);
617 }
618 } catch (IndexOutOfBoundsException ioobe) {
619 r.putError(tr("The \"{0}\" way must contain at least 2 nodes.", "from"), true);
620 }
621
622 // find the "direct" node after the via node
623 Node toNode = null;
624 try
625 {
626 if(toWay.nodes.get(0) == via) {
627 if(restrictionDebug)
628 System.out.println("To way heading away from via");
629 toNode = toWay.nodes.get(1);
630 } else {
631 if(restrictionDebug)
632 System.out.println("To way heading towards via");
633 toNode = toWay.nodes.get(toWay.nodes.size()-2);
634 }
635 } catch (IndexOutOfBoundsException ioobe) {
636 r.putError(tr("The \"{0}\" way must contain at least 2 nodes.", "to"), true);
637 }
638
639 Point pFrom = nc.getPoint(fromNode.eastNorth);
640 Point pVia = nc.getPoint(via.eastNorth);
641
642 if(restrictionDebug) {
643 Point pTo = nc.getPoint(toNode.eastNorth);
644
645 // debug output of interesting nodes
646 System.out.println("From: " + fromNode);
647 drawNode(fromNode, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
648 System.out.println("Via: " + via);
649 drawNode(via, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
650 System.out.println("To: " + toNode);
651 drawNode(toNode, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
652 System.out.println("From X: " + pFrom.x + " Y " + pFrom.y);
653 System.out.println("Via X: " + pVia.x + " Y " + pVia.y);
654 System.out.println("To X: " + pTo.x + " Y " + pTo.y);
655 }
656
657 // starting from via, go back the "from" way a few pixels
658 // (calculate the vector vx/vy with the specified length and the direction away from the "via" node along the first segment of the "from" way)
659 double distanceFromVia=14;
660 double dx = (pFrom.x >= pVia.x) ? (pFrom.x - pVia.x) : (pVia.x - pFrom.x);
661 double dy = (pFrom.y >= pVia.y) ? (pFrom.y - pVia.y) : (pVia.y - pFrom.y);
662
663 double fromAngle;
664 if(dx == 0.0) {
665 fromAngle = Math.PI/2;
666 } else {
667 fromAngle = Math.atan(dy / dx);
668 }
669 double fromAngleDeg = Math.toDegrees(fromAngle);
670
671 double vx = distanceFromVia * Math.cos(fromAngle);
672 double vy = distanceFromVia * Math.sin(fromAngle);
673
674 if(pFrom.x < pVia.x) vx = -vx;
675 if(pFrom.y < pVia.y) vy = -vy;
676
677 if(restrictionDebug)
678 System.out.println("vx " + vx + " vy " + vy);
679
680 // go a few pixels away from the way (in a right angle)
681 // (calculate the vx2/vy2 vector with the specified length and the direction 90degrees away from the first segment of the "from" way)
682 double distanceFromWay=8;
683 double vx2 = 0;
684 double vy2 = 0;
685 double iconAngle = 0;
686
687 if(pFrom.x >= pVia.x && pFrom.y >= pVia.y) {
688 if(!leftHandTraffic) {
689 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90));
690 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90));
691 } else {
692 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90));
693 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90));
694 }
695 iconAngle = 270+fromAngleDeg;
696 }
697 if(pFrom.x < pVia.x && pFrom.y >= pVia.y) {
698 if(!leftHandTraffic) {
699 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
700 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
701 } else {
702 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180));
703 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180));
704 }
705 iconAngle = 90-fromAngleDeg;
706 }
707 if(pFrom.x < pVia.x && pFrom.y < pVia.y) {
708 if(!leftHandTraffic) {
709 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90));
710 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90));
711 } else {
712 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90));
713 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90));
714 }
715 iconAngle = 90+fromAngleDeg;
716 }
717 if(pFrom.x >= pVia.x && pFrom.y < pVia.y) {
718 if(!leftHandTraffic) {
719 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180));
720 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180));
721 } else {
722 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
723 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
724 }
725 iconAngle = 270-fromAngleDeg;
726 }
727
728 IconElemStyle nodeStyle = getPrimitiveNodeStyle(r);
729
730 if (nodeStyle == null) {
731 r.putError(tr("Style for restriction {0} not found.", r.keys.get("restriction")), true);
732 return;
733 }
734
735 // rotate icon with direction last node in from to
736 if(restrictionDebug)
737 System.out.println("Deg1 " + fromAngleDeg + " Deg2 " + (fromAngleDeg + 180) + " Icon " + iconAngle);
738 ImageIcon rotatedIcon = ImageProvider.createRotatedImage(null /*icon2*/, nodeStyle.icon, iconAngle);
739
740 // scale down icon to 16*16 pixels
741 ImageIcon smallIcon = new ImageIcon(rotatedIcon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH));
742 int w = smallIcon.getIconWidth(), h=smallIcon.getIconHeight();
743 smallIcon.paintIcon ( Main.map.mapView, g, (int)(pVia.x+vx+vx2)-w/2, (int)(pVia.y+vy+vy2)-h/2 );
744
745 if (r.selected)
746 {
747 g.setColor ( selectedColor );
748 g.drawRect ((int)(pVia.x+vx+vx2)-w/2-2,(int)(pVia.y+vy+vy2)-h/2-2, w+4, h+4);
749 }
750 }
751
752 public Boolean drawMultipolygon(Relation r) {
753 Collection<Way> inner = new LinkedList<Way>();
754 Collection<Way> outer = new LinkedList<Way>();
755 Collection<Way> innerclosed = new LinkedList<Way>();
756 Collection<Way> outerclosed = new LinkedList<Way>();
757 Boolean incomplete = false;
758 Boolean drawn = false;
759
760 r.clearErrors();
761
762 for (RelationMember m : r.members)
763 {
764 if(m.member == null)
765 r.putError(tr("Empty member in relation."), true);
766 else if(m.member.deleted)
767 r.putError(tr("Deleted member ''{0}'' in relation.",
768 m.member.getName()), true);
769 else if(m.member.incomplete)
770 incomplete = true;
771 else
772 {
773 if(m.member instanceof Way)
774 {
775 Way w = (Way) m.member;
776 if(w.nodes.size() < 2)
777 {
778 r.putError(tr("Way ''{0}'' with less than two points.",
779 w.getName()), true);
780 }
781 else if("inner".equals(m.role))
782 inner.add(w);
783 else if("outer".equals(m.role))
784 outer.add(w);
785 else
786 {
787 r.putError(tr("No useful role ''{0}'' for Way ''{1}''.",
788 m.role == null ? "" : m.role, w.getName()), true);
789 if(m.role == null || m.role.length() == 0)
790 outer.add(w);
791 else if(r.selected)
792 drawSelectedMember(m.member, styles != null
793 ? getPrimitiveStyle(m.member) : null, true, true);
794 }
795 }
796 else
797 {
798 r.putError(tr("Non-Way ''{0}'' in multipolygon.",
799 m.member.getName()), true);
800 }
801 }
802 }
803
804 ElemStyle wayStyle = styles != null ? getPrimitiveStyle(r) : null;
805 if(styles != null && (wayStyle == null || !(wayStyle instanceof AreaElemStyle)))
806 {
807 for (Way w : outer)
808 {
809 if(wayStyle == null || !(wayStyle instanceof AreaElemStyle))
810 wayStyle = styles.get(w);
811 }
812 r.mappaintStyle = wayStyle;
813 }
814
815 if(wayStyle != null && wayStyle instanceof AreaElemStyle)
816 {
817 Boolean zoomok = isZoomOk(wayStyle);
818 Boolean visible = false;
819 Collection<Way> join = new LinkedList<Way>();
820
821 drawn = true;
822 for (Way w : outer)
823 {
824 if(w.isClosed()) outerclosed.add(w);
825 else join.add(w);
826 }
827 if(join.size() != 0)
828 {
829 for(Way w : joinWays(join, incomplete ? null : r))
830 outerclosed.add(w);
831 }
832
833 join.clear();
834 for (Way w : inner)
835 {
836 if(w.isClosed()) innerclosed.add(w);
837 else join.add(w);
838 }
839 if(join.size() != 0)
840 {
841 for(Way w : joinWays(join, incomplete ? null : r))
842 innerclosed.add(w);
843 }
844
845 if(outerclosed.size() == 0)
846 {
847 r.putError(tr("No outer way for multipolygon ''{0}''.",
848 r.getName()), true);
849 visible = true; /* prevent killing remaining ways */
850 }
851 else if(zoomok)
852 {
853 class PolyData {
854 public Polygon poly = new Polygon();
855 public Way way;
856 private Point p = null;
857 private Collection<Polygon> inner = null;
858 PolyData(Way w)
859 {
860 way = w;
861 for (Node n : w.nodes)
862 {
863 p = nc.getPoint(n.eastNorth);
864 poly.addPoint(p.x,p.y);
865 }
866 }
867 public int contains(Polygon p)
868 {
869 int contains = p.npoints;
870 for(int i = 0; i < p.npoints; ++i)
871 {
872 if(poly.contains(p.xpoints[i],p.ypoints[i]))
873 --contains;
874 }
875 if(contains == 0) return 1;
876 if(contains == p.npoints) return 0;
877 return 2;
878 }
879 public void addInner(Polygon p)
880 {
881 if(inner == null)
882 inner = new ArrayList<Polygon>();
883 inner.add(p);
884 }
885 public Polygon get()
886 {
887 if(inner != null)
888 {
889 for (Polygon pp : inner)
890 {
891 for(int i = 0; i < pp.npoints; ++i)
892 poly.addPoint(pp.xpoints[i],pp.ypoints[i]);
893 poly.addPoint(p.x,p.y);
894 }
895 inner = null;
896 }
897 return poly;
898 }
899 }
900 LinkedList<PolyData> poly = new LinkedList<PolyData>();
901 for (Way w : outerclosed)
902 {
903 poly.add(new PolyData(w));
904 }
905 for (Way wInner : innerclosed)
906 {
907 Polygon polygon = new Polygon();
908
909 for (Node n : wInner.nodes)
910 {
911 Point pInner = nc.getPoint(n.eastNorth);
912 polygon.addPoint(pInner.x,pInner.y);
913 }
914 if(!wInner.isClosed())
915 {
916 Point pInner = nc.getPoint(wInner.nodes.get(0).eastNorth);
917 polygon.addPoint(pInner.x,pInner.y);
918 }
919 PolyData o = null;
920 for (PolyData pd : poly)
921 {
922 Integer c = pd.contains(polygon);
923 if(c >= 1)
924 {
925 if(c > 1 && pd.way.isClosed())
926 {
927 r.putError(tr("Intersection between ways ''{0}'' and ''{1}''.",
928 pd.way.getName(), wInner.getName()), true);
929 }
930 if(o == null || o.contains(pd.poly) > 0)
931 o = pd;
932 }
933 }
934 if(o == null)
935 {
936 if(!incomplete)
937 {
938 r.putError(tr("Inner way ''{0}'' is outside.",
939 wInner.getName()), true);
940 }
941 o = poly.get(0);
942 }
943 o.addInner(polygon);
944 }
945 for (PolyData pd : poly)
946 {
947 if(isPolygonVisible(pd.get()))
948 {
949 drawAreaPolygon(pd.get(), (pd.way.selected || r.selected) ? selectedColor
950 : ((AreaElemStyle)wayStyle).color);
951 visible = true;
952 }
953 }
954 }
955 if(!visible) /* nothing visible, so disable relation and all its ways */
956 {
957 r.mappaintVisibleCode = viewid;
958 for (Way wInner : inner)
959 wInner.mappaintVisibleCode = viewid;
960 for (Way wOuter : outer)
961 wOuter.mappaintVisibleCode = viewid;
962 return drawn;
963 }
964 for (Way wInner : inner)
965 {
966 ElemStyle innerStyle = getPrimitiveStyle(wInner);
967 if(innerStyle == null)
968 {
969 if(zoomok && (wInner.mappaintDrawnCode != paintid
970 || outer.size() == 0))
971 {
972 drawWay(wInner, ((AreaElemStyle)wayStyle).line,
973 ((AreaElemStyle)wayStyle).color, wInner.selected
974 || r.selected);
975 }
976 wInner.mappaintDrawnCode = paintid;
977 }
978 else
979 {
980 if(r.selected)
981 {
982 drawSelectedMember(wInner, innerStyle,
983 !wayStyle.equals(innerStyle), wInner.selected);
984 }
985 if(wayStyle.equals(innerStyle))
986 {
987 r.putError(tr("Style for inner way ''{0}'' equals multipolygon.",
988 wInner.getName()), false);
989 if(!r.selected)
990 wInner.mappaintDrawnAreaCode = paintid;
991 }
992 }
993 }
994 for (Way wOuter : outer)
995 {
996 ElemStyle outerStyle = getPrimitiveStyle(wOuter);
997 if(outerStyle == null)
998 {
999 if(zoomok)
1000 {
1001 drawWay(wOuter, ((AreaElemStyle)wayStyle).line,
1002 ((AreaElemStyle)wayStyle).color, wOuter.selected
1003 || r.selected);
1004 }
1005 wOuter.mappaintDrawnCode = paintid;
1006 }
1007 else
1008 {
1009 if(outerStyle instanceof AreaElemStyle
1010 && !wayStyle.equals(outerStyle))
1011 {
1012 r.putError(tr("Style for outer way ''{0}'' mismatches.",
1013 wOuter.getName()), true);
1014 }
1015 if(r.selected)
1016 {
1017 drawSelectedMember(wOuter, outerStyle, false, false);
1018 }
1019 else if(outerStyle instanceof AreaElemStyle)
1020 wOuter.mappaintDrawnAreaCode = paintid;
1021 }
1022 }
1023 }
1024 return drawn;
1025 }
1026
1027 protected Polygon getPolygon(Way w)
1028 {
1029 Polygon polygon = new Polygon();
1030
1031 for (Node n : w.nodes)
1032 {
1033 Point p = nc.getPoint(n.eastNorth);
1034 polygon.addPoint(p.x,p.y);
1035 }
1036 return polygon;
1037 }
1038
1039 protected void drawArea(Way w, Color color)
1040 {
1041 Polygon polygon = getPolygon(w);
1042
1043 // set the opacity (alpha) level of the filled polygon
1044 g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
1045 g.fillPolygon(polygon);
1046 }
1047
1048 protected void drawAreaPolygon(Polygon polygon, Color color)
1049 {
1050 // set the opacity (alpha) level of the filled polygon
1051 g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
1052 g.fillPolygon(polygon);
1053 }
1054
1055 protected void drawNode(Node n, ImageIcon icon, boolean annotate, Boolean selected) {
1056 Point p = nc.getPoint(n.eastNorth);
1057 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
1058
1059 profilerVisibleNodes++;
1060
1061 int w = icon.getIconWidth(), h=icon.getIconHeight();
1062 icon.paintIcon ( Main.map.mapView, g, p.x-w/2, p.y-h/2 );
1063 if(showNames > dist)
1064 {
1065 String name = getNodeName(n);
1066 if (name!=null && annotate)
1067 {
1068 g.setColor(textColor);
1069 Font defaultFont = g.getFont();
1070 g.setFont (orderFont);
1071 g.drawString (name, p.x+w/2+2, p.y+h/2+2);
1072 g.setFont(defaultFont);
1073 }
1074 }
1075 if (selected)
1076 {
1077 g.setColor ( selectedColor );
1078 g.drawRect (p.x-w/2-2, p.y-h/2-2, w+4, h+4);
1079 }
1080 }
1081
1082 protected String getNodeName(Node n) {
1083 String name = null;
1084 if (n.keys != null) {
1085 for (int i = 0; i < regionalNameOrder.length; i++) {
1086 name = n.keys.get(regionalNameOrder[i]);
1087 if (name != null) break;
1088 }
1089 }
1090 return name;
1091 }
1092
1093 private void drawSeg(Node n1, Node n2, Color col, boolean showDirection, int width, int dashed, Color dashedColor) {
1094 profilerSegments++;
1095 if (col != currentColor || width != currentWidth || dashed != currentDashed || dashedColor != currentDashedColor) {
1096 displaySegments(col, width, dashed, dashedColor);
1097 }
1098 Point p1 = nc.getPoint(n1.eastNorth);
1099 Point p2 = nc.getPoint(n2.eastNorth);
1100
1101 if (!isSegmentVisible(p1, p2)) {
1102 return;
1103 }
1104 profilerVisibleSegments++;
1105 currentPath.moveTo(p1.x, p1.y);
1106 currentPath.lineTo(p2.x, p2.y);
1107
1108 if (showDirection) {
1109 double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
1110 currentPath.lineTo((int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
1111 currentPath.moveTo((int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
1112 currentPath.lineTo(p2.x, p2.y);
1113 }
1114 }
1115
1116 protected void displaySegments() {
1117 displaySegments(null, 0, 0, null);
1118 }
1119
1120 protected void displaySegments(Color newColor, int newWidth, int newDash, Color newDashedColor) {
1121 if (currentPath != null) {
1122 Graphics2D g2d = (Graphics2D)g;
1123 g2d.setColor(inactive ? inactiveColor : currentColor);
1124 if (currentStroke == null && useStrokes > dist) {
1125 if (currentDashed != 0)
1126 g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,new float[] {currentDashed},0));
1127 else
1128 g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
1129 }
1130 g2d.draw(currentPath);
1131
1132 if(currentDashedColor != null) {
1133 g2d.setColor(currentDashedColor);
1134 if (currentStroke == null && useStrokes > dist) {
1135 if (currentDashed != 0)
1136 g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,new float[] {currentDashed},currentDashed));
1137 else
1138 g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
1139 }
1140 g2d.draw(currentPath);
1141 }
1142
1143 if(useStrokes > dist)
1144 g2d.setStroke(new BasicStroke(1));
1145
1146 currentPath = new GeneralPath();
1147 currentColor = newColor;
1148 currentWidth = newWidth;
1149 currentDashed = newDash;
1150 currentDashedColor = newDashedColor;
1151 currentStroke = null;
1152 }
1153 }
1154
1155 /**
1156 * Draw the node as small rectangle with the given color.
1157 *
1158 * @param n The node to draw.
1159 * @param color The color of the node.
1160 */
1161 public void drawNode(Node n, Color color, int size, int radius, boolean fill) {
1162 if (isZoomOk(null) && size > 1) {
1163 Point p = nc.getPoint(n.eastNorth);
1164 if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth())
1165 || (p.y > nc.getHeight()))
1166 return;
1167
1168 profilerVisibleNodes++;
1169
1170 g.setColor(color);
1171 if (fill) {
1172 g.fillRect(p.x - radius, p.y - radius, size, size);
1173 g.drawRect(p.x - radius, p.y - radius, size, size);
1174 } else
1175 g.drawRect(p.x - radius, p.y - radius, size, size);
1176
1177 if(showNames > dist)
1178 {
1179 String name = getNodeName(n);
1180 if (name!=null /* && annotate */)
1181 {
1182 g.setColor(textColor);
1183 Font defaultFont = g.getFont();
1184 g.setFont (orderFont);
1185 g.drawString (name, p.x+radius+2, p.y+radius+2);
1186 g.setFont(defaultFont);
1187 }
1188 }
1189 }
1190 }
1191
1192 public void getColors()
1193 {
1194 super.getColors();
1195 untaggedColor = Main.pref.getColor(marktr("untagged"),Color.GRAY);
1196 textColor = Main.pref.getColor (marktr("text"), Color.WHITE);
1197 }
1198
1199 // Shows areas before non-areas
1200 public void visitAll(DataSet data, Boolean virtual) {
1201
1202 boolean profiler = Main.pref.getBoolean("mappaint.profiler",false);
1203 profilerOmitDraw = Main.pref.getBoolean("mappaint.profiler.omitdraw",false);
1204
1205 useStyleCache = Main.pref.getBoolean("mappaint.cache",true);
1206 fillAreas = Main.pref.getInteger("mappaint.fillareas", 10000000);
1207 fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref.getInteger("mappaint.fillalpha", 50))));
1208 showNames = Main.pref.getInteger("mappaint.shownames", 10000000);
1209 showIcons = Main.pref.getInteger("mappaint.showicons", 10000000);
1210 useStrokes = Main.pref.getInteger("mappaint.strokes", 10000000);
1211 LatLon ll1 = nc.getLatLon(0,0);
1212 LatLon ll2 = nc.getLatLon(100,0);
1213 dist = ll1.greatCircleDistance(ll2);
1214
1215 long profilerStart = java.lang.System.currentTimeMillis();
1216 long profilerLast = profilerStart;
1217 int profilerN;
1218 if(profiler)
1219 System.out.println("Mappaint Profiler (" +
1220 (useStyleCache ? "cache=true, " : "cache=false, ") +
1221 "fillareas " + fillAreas + ", " +
1222 "fillalpha=" + fillAlpha + "%, " +
1223 "dist=" + (int)dist + "m)");
1224
1225 getSettings(virtual);
1226 useRealWidth = Main.pref.getBoolean("mappaint.useRealWidth",false);
1227 zoomLevelDisplay = Main.pref.getBoolean("mappaint.zoomLevelDisplay",false);
1228 circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; // circumference of the earth in meter
1229 styles = MapPaintStyles.getStyles().getStyleSet();
1230 drawMultipolygon = Main.pref.getBoolean("mappaint.multipolygon",true);
1231 drawRestriction = Main.pref.getBoolean("mappaint.restriction",true);
1232 restrictionDebug = Main.pref.getBoolean("mappaint.restriction.debug",false);
1233 leftHandTraffic = Main.pref.getBoolean("mappaint.lefthandtraffic",false);
1234 orderFont = new Font(Main.pref.get("mappaint.font","Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8));
1235 String currentLocale = Locale.getDefault().getLanguage();
1236 regionalNameOrder = Main.pref.get("mappaint.nameOrder", "name:"+currentLocale+";name;int_name;ref;operator;brand").split(";");
1237 minEN = nc.getEastNorth(0,nc.getHeight()-1);
1238 maxEN = nc.getEastNorth(nc.getWidth()-1,0);
1239
1240
1241 selectedCall = false;
1242 ++paintid;
1243 viewid = nc.getViewID();
1244
1245 profilerVisibleNodes = 0;
1246 profilerVisibleWays = 0;
1247 profilerVisibleAreas = 0;
1248 profilerSegments = 0;
1249 profilerVisibleSegments = 0;
1250
1251 if(profiler)
1252 {
1253 System.out.format("Prepare : %5dms\n", (java.lang.System.currentTimeMillis()-profilerLast));
1254 profilerLast = java.lang.System.currentTimeMillis();
1255 }
1256
1257 if (fillAreas > dist && styles != null && styles.hasAreas()) {
1258 Collection<Way> noAreaWays = new LinkedList<Way>();
1259
1260 /*** RELATIONS ***/
1261 profilerN = 0;
1262 for (final Relation osm : data.relations)
1263 {
1264 if(!osm.deleted && !osm.incomplete && osm.mappaintVisibleCode != viewid)
1265 {
1266 osm.visit(this);
1267 profilerN++;
1268 }
1269 }
1270
1271 if(profiler)
1272 {
1273 System.out.format("Relations: %5dms, calls=%7d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
1274 profilerLast = java.lang.System.currentTimeMillis();
1275 }
1276
1277 /*** AREAS ***/
1278 profilerN = 0;
1279 for (final Way osm : data.ways)
1280 {
1281 if (!osm.incomplete && !osm.deleted
1282 && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
1283 {
1284 if(isPrimitiveArea(osm) && osm.mappaintDrawnAreaCode != paintid)
1285 {
1286 osm.visit(this);
1287 profilerN++;
1288 } else
1289 noAreaWays.add((Way)osm);
1290 }
1291 }
1292
1293 if(profiler)
1294 {
1295 System.out.format("Areas : %5dms, calls=%7d, visible=%d\n",
1296 (java.lang.System.currentTimeMillis()-profilerLast), profilerN, profilerVisibleAreas);
1297 profilerLast = java.lang.System.currentTimeMillis();
1298 }
1299
1300 /*** WAYS ***/
1301 profilerN = 0;
1302 fillAreas = 0;
1303 for (final OsmPrimitive osm : noAreaWays)
1304 {
1305 osm.visit(this);
1306 profilerN++;
1307 }
1308
1309 if(profiler)
1310 {
1311 System.out.format("Ways : %5dms, calls=%7d, visible=%d\n",
1312 (java.lang.System.currentTimeMillis()-profilerLast), profilerN, profilerVisibleWays);
1313 profilerLast = java.lang.System.currentTimeMillis();
1314 }
1315 }
1316 else
1317 {
1318 /*** WAYS (filling disabled) ***/
1319 profilerN = 0;
1320 for (final OsmPrimitive osm : data.ways)
1321 if (!osm.incomplete && !osm.deleted && !osm.selected
1322 && osm.mappaintVisibleCode != viewid )
1323 {
1324 osm.visit(this);
1325 profilerN++;
1326 }
1327
1328 if(profiler)
1329 {
1330 System.out.format("Ways : %5dms, calls=%7d, visible=%d\n",
1331 (java.lang.System.currentTimeMillis()-profilerLast), profilerN, profilerVisibleWays);
1332 profilerLast = java.lang.System.currentTimeMillis();
1333 }
1334 }
1335
1336 /*** SELECTED ***/
1337 selectedCall = true;
1338 profilerN = 0;
1339 for (final OsmPrimitive osm : data.getSelected()) {
1340 if (!osm.incomplete && !osm.deleted && !(osm instanceof Node)
1341 && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
1342 {
1343 osm.visit(this);
1344 profilerN++;
1345 }
1346 }
1347
1348 if(profiler)
1349 {
1350 System.out.format("Selected : %5dms, calls=%7d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
1351 profilerLast = java.lang.System.currentTimeMillis();
1352 }
1353
1354 /*** DISPLAY CACHED SEGMENTS (WAYS) NOW ***/
1355 displaySegments();
1356
1357 /*** NODES ***/
1358 profilerN = 0;
1359 for (final OsmPrimitive osm : data.nodes)
1360 if (!osm.incomplete && !osm.deleted
1361 && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
1362 {
1363 osm.visit(this);
1364 profilerN++;
1365 }
1366
1367 if(profiler)
1368 {
1369 System.out.format("Nodes : %5dms, calls=%7d, visible=%d\n",
1370 (java.lang.System.currentTimeMillis()-profilerLast), profilerN, profilerVisibleNodes);
1371 profilerLast = java.lang.System.currentTimeMillis();
1372 }
1373
1374 /*** VIRTUAL ***/
1375 if (virtualNodeSize != 0)
1376 {
1377 profilerN = 0;
1378 currentColor = nodeColor;
1379 for (final OsmPrimitive osm : data.ways)
1380 if (!osm.incomplete && !osm.deleted
1381 && osm.mappaintVisibleCode != viewid )
1382 {
1383 // TODO: move this into the SimplePaint code?
1384 if(!profilerOmitDraw)
1385 visitVirtual((Way)osm);
1386 profilerN++;
1387 }
1388
1389 if(profiler)
1390 {
1391 System.out.format("Virtual : %5dms, calls=%7d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
1392 profilerLast = java.lang.System.currentTimeMillis();
1393 }
1394
1395 displaySegments(null);
1396 }
1397
1398 if(profiler)
1399 {
1400 System.out.format("Segments : calls=%7d, visible=%d\n", profilerSegments, profilerVisibleSegments);
1401 System.out.format("All : %5dms\n", (profilerLast-profilerStart));
1402 }
1403 }
1404
1405 /**
1406 * Draw a number of the order of the two consecutive nodes within the
1407 * parents way
1408 */
1409 protected void drawOrderNumber(Node n1, Node n2, int orderNumber) {
1410 Point p1 = nc.getPoint(n1.eastNorth);
1411 Point p2 = nc.getPoint(n2.eastNorth);
1412 drawOrderNumber(p1, p2, orderNumber);
1413 }
1414}
Note: See TracBrowser for help on using the repository browser.