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

Last change on this file since 1990 was 1990, checked in by Gubaer, 15 years ago

fixed #3261: Use the "name:$CURRENT_LOCALE" name in the JOSM UI instead of "name" when it exists
new: new checkbox in LAF preferences for enabling/disabling localized names for primitives

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