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

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

see #3697: way member of relation can't be selected in version 2276 SVN

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