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

Last change on this file since 2206 was 2206, checked in by jttt, 15 years ago

Minor optimalizations

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