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

Last change on this file since 3167 was 3167, checked in by jttt, 14 years ago

Added mappaint performance test

  • Property svn:eol-style set to native
File size: 27.9 KB
Line 
1/* License: GPL. Copyright 2007 by Immanuel Scholz and others */
2package org.openstreetmap.josm.data.osm.visitor.paint;
3
4/* To enable debugging or profiling remove the double / signs */
5
6import static org.openstreetmap.josm.tools.I18n.tr;
7
8import java.awt.Graphics2D;
9import java.awt.Point;
10import java.awt.Polygon;
11import java.awt.Rectangle;
12import java.awt.RenderingHints;
13import java.awt.geom.Point2D;
14import java.util.ArrayList;
15import java.util.Collection;
16import java.util.Collections;
17import java.util.Comparator;
18import java.util.LinkedList;
19
20import org.openstreetmap.josm.Main;
21import org.openstreetmap.josm.data.Bounds;
22import org.openstreetmap.josm.data.coor.EastNorth;
23import org.openstreetmap.josm.data.coor.LatLon;
24import org.openstreetmap.josm.data.osm.BBox;
25import org.openstreetmap.josm.data.osm.DataSet;
26import org.openstreetmap.josm.data.osm.Node;
27import org.openstreetmap.josm.data.osm.OsmPrimitive;
28import org.openstreetmap.josm.data.osm.OsmUtils;
29import org.openstreetmap.josm.data.osm.Relation;
30import org.openstreetmap.josm.data.osm.RelationMember;
31import org.openstreetmap.josm.data.osm.Way;
32import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
33import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
34import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData;
35import org.openstreetmap.josm.gui.DefaultNameFormatter;
36import org.openstreetmap.josm.gui.NavigatableComponent;
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.gui.mappaint.SimpleNodeElemStyle;
44
45public class MapPaintVisitor implements PaintVisitor {
46
47 private Graphics2D g;
48 private NavigatableComponent nc;
49
50 private boolean zoomLevelDisplay;
51 private boolean drawMultipolygon;
52 private boolean drawRestriction;
53 private boolean leftHandTraffic;
54 private ElemStyles.StyleSet styles;
55 private double circum;
56 private double dist;
57 private boolean useStyleCache;
58 private static int paintid = 0;
59 private EastNorth minEN;
60 private EastNorth maxEN;
61 private MapPainter painter;
62 private MapPaintSettings paintSettings;
63
64 private boolean inactive;
65
66 protected boolean isZoomOk(ElemStyle e) {
67 if (!zoomLevelDisplay) /* show everything if the user wishes so */
68 return true;
69
70 if(e == null) /* the default for things that don't have a rule (show, if scale is smaller than 1500m) */
71 return (circum < 1500);
72
73 return !(circum >= e.maxScale || circum < e.minScale);
74 }
75
76 public ElemStyle getPrimitiveStyle(OsmPrimitive osm) {
77 if(!useStyleCache)
78 return ((styles != null) ? styles.get(osm) : null);
79
80 if(osm.mappaintStyle == null && styles != null) {
81 osm.mappaintStyle = styles.get(osm);
82 if(osm instanceof Way) {
83 ((Way)osm).isMappaintArea = styles.isArea(osm);
84 }
85 }
86
87 if (osm.mappaintStyle == null && osm instanceof Node) {
88 osm.mappaintStyle = SimpleNodeElemStyle.INSTANCE;
89 }
90
91 if (osm.mappaintStyle == null && osm instanceof Way) {
92 osm.mappaintStyle = LineElemStyle.UNTAGGED_WAY;
93 }
94
95 return osm.mappaintStyle;
96 }
97
98 public IconElemStyle getPrimitiveNodeStyle(OsmPrimitive osm) {
99 if(!useStyleCache)
100 return (styles != null) ? styles.getIcon(osm) : null;
101
102 if(osm.mappaintStyle == null && styles != null) {
103 osm.mappaintStyle = styles.getIcon(osm);
104 }
105
106 return (IconElemStyle)osm.mappaintStyle;
107 }
108
109 public boolean isPrimitiveArea(Way osm) {
110 if(!useStyleCache)
111 return styles.isArea(osm);
112
113 if(osm.mappaintStyle == null && styles != null) {
114 osm.mappaintStyle = styles.get(osm);
115 osm.isMappaintArea = styles.isArea(osm);
116 }
117 return osm.isMappaintArea;
118 }
119
120 public void drawNode(Node n) {
121 /* check, if the node is visible at all */
122 if((n.getEastNorth().east() > maxEN.east() ) ||
123 (n.getEastNorth().north() > maxEN.north()) ||
124 (n.getEastNorth().east() < minEN.east() ) ||
125 (n.getEastNorth().north() < minEN.north()))
126 return;
127
128 ElemStyle nodeStyle = getPrimitiveStyle(n);
129
130 if (isZoomOk(nodeStyle)) {
131 nodeStyle.paintPrimitive(n, paintSettings, painter, n.isSelected());
132 }
133 }
134
135 public void drawWay(Way w, int fillAreas) {
136 if(w.getNodesCount() < 2)
137 return;
138
139 if (w.hasIncompleteNodes())
140 return;
141
142 /* check, if the way is visible at all */
143 double minx = 10000;
144 double maxx = -10000;
145 double miny = 10000;
146 double maxy = -10000;
147
148 for (Node n : w.getNodes())
149 {
150 if(n.getEastNorth().east() > maxx) {
151 maxx = n.getEastNorth().east();
152 }
153 if(n.getEastNorth().north() > maxy) {
154 maxy = n.getEastNorth().north();
155 }
156 if(n.getEastNorth().east() < minx) {
157 minx = n.getEastNorth().east();
158 }
159 if(n.getEastNorth().north() < miny) {
160 miny = n.getEastNorth().north();
161 }
162 }
163
164 if ((minx > maxEN.east()) ||
165 (miny > maxEN.north()) ||
166 (maxx < minEN.east()) ||
167 (maxy < minEN.north()))
168 return;
169
170 ElemStyle wayStyle = getPrimitiveStyle(w);
171
172 if(!isZoomOk(wayStyle))
173 return;
174
175 if (wayStyle == null) {
176 wayStyle = LineElemStyle.UNTAGGED_WAY;
177 }
178
179 if(wayStyle instanceof LineElemStyle) {
180 wayStyle.paintPrimitive(w, paintSettings, painter, data.isSelected(w));
181 } else if (wayStyle instanceof AreaElemStyle) {
182 AreaElemStyle areaStyle = (AreaElemStyle) wayStyle;
183 /* way with area style */
184 if (fillAreas > dist)
185 {
186 painter.drawArea(getPolygon(w), (data.isSelected(w) ? paintSettings.getSelectedColor() : areaStyle.color), painter.getWayName(w));
187 if(!w.isClosed()) {
188 putError(w, tr("Area style way is not closed."), true);
189 }
190 }
191 areaStyle.getLineStyle().paintPrimitive(w, paintSettings, painter, data.isSelected(w));
192 }
193 }
194
195 public void drawSelectedMember(OsmPrimitive osm, ElemStyle style, boolean area,
196 boolean areaselected)
197 {
198 if(osm instanceof Way)
199 {
200 if(style instanceof AreaElemStyle) {
201 Way way = (Way)osm;
202 AreaElemStyle areaStyle = (AreaElemStyle)style;
203 areaStyle.getLineStyle().paintPrimitive(way, paintSettings, painter, true);
204 if(area) {
205 painter.drawArea(getPolygon(way), (areaselected ? paintSettings.getSelectedColor() : areaStyle.color), painter.getWayName(way));
206 }
207 } else {
208 style.paintPrimitive(osm, paintSettings, painter, true);
209 }
210 }
211 else if(osm instanceof Node)
212 {
213 if(isZoomOk(style)) {
214 style.paintPrimitive(osm, paintSettings, painter, true);
215 }
216 }
217 osm.mappaintDrawnCode = paintid;
218 }
219
220 public void paintUnselectedRelation(Relation r) {
221
222 if (drawMultipolygon && "multipolygon".equals(r.get("type")))
223 {
224 if(drawMultipolygon(r))
225 return;
226 }
227 else if (drawRestriction && "restriction".equals(r.get("type")))
228 {
229 drawRestriction(r);
230 }
231
232 if(data.isSelected(r)) /* draw ways*/
233 {
234 for (RelationMember m : r.getMembers())
235 {
236 if (m.isWay() && m.getMember().isDrawable())
237 {
238 drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember())
239 : null, true, true);
240 }
241 }
242 }
243 }
244
245 public void drawRestriction(Relation r) {
246
247 Way fromWay = null;
248 Way toWay = null;
249 OsmPrimitive via = null;
250
251 /* find the "from", "via" and "to" elements */
252 for (RelationMember m : r.getMembers())
253 {
254 if(m.getMember().isIncomplete())
255 return;
256 else
257 {
258 if(m.isWay())
259 {
260 Way w = m.getWay();
261 if(w.getNodesCount() < 2) {
262 continue;
263 }
264
265 if("from".equals(m.getRole())) {
266 if(fromWay != null) {
267 putError(r, tr("More than one \"from\" way found."), true);
268 } else {
269 fromWay = w;
270 }
271 } else if("to".equals(m.getRole())) {
272 if(toWay != null) {
273 putError(r, tr("More than one \"to\" way found."), true);
274 } else {
275 toWay = w;
276 }
277 } else if("via".equals(m.getRole())) {
278 if(via != null) {
279 putError(r, tr("More than one \"via\" found."), true);
280 } else {
281 via = w;
282 }
283 } else {
284 putError(r, tr("Unknown role ''{0}''.", m.getRole()), true);
285 }
286 }
287 else if(m.isNode())
288 {
289 Node n = m.getNode();
290 if("via".equals(m.getRole()))
291 {
292 if(via != null) {
293 putError(r, tr("More than one \"via\" found."), true);
294 } else {
295 via = n;
296 }
297 } else {
298 putError(r, tr("Unknown role ''{0}''.", m.getRole()), true);
299 }
300 } else {
301 putError(r, tr("Unknown member type for ''{0}''.", m.getMember().getDisplayName(DefaultNameFormatter.getInstance())), true);
302 }
303 }
304 }
305
306 if (fromWay == null) {
307 putError(r, tr("No \"from\" way found."), true);
308 return;
309 }
310 if (toWay == null) {
311 putError(r, tr("No \"to\" way found."), true);
312 return;
313 }
314 if (via == null) {
315 putError(r, tr("No \"via\" node or way found."), true);
316 return;
317 }
318
319 Node viaNode;
320 if(via instanceof Node)
321 {
322 viaNode = (Node) via;
323 if(!fromWay.isFirstLastNode(viaNode)) {
324 putError(r, tr("The \"from\" way does not start or end at a \"via\" node."), true);
325 return;
326 }
327 if(!toWay.isFirstLastNode(viaNode)) {
328 putError(r, tr("The \"to\" way does not start or end at a \"via\" node."), true);
329 }
330 }
331 else
332 {
333 Way viaWay = (Way) via;
334 Node firstNode = viaWay.firstNode();
335 Node lastNode = viaWay.lastNode();
336 Boolean onewayvia = false;
337
338 String onewayviastr = viaWay.get("oneway");
339 if(onewayviastr != null)
340 {
341 if("-1".equals(onewayviastr)) {
342 onewayvia = true;
343 Node tmp = firstNode;
344 firstNode = lastNode;
345 lastNode = tmp;
346 } else {
347 onewayvia = OsmUtils.getOsmBoolean(onewayviastr);
348 if (onewayvia == null) {
349 onewayvia = false;
350 }
351 }
352 }
353
354 if(fromWay.isFirstLastNode(firstNode)) {
355 viaNode = firstNode;
356 } else if (!onewayvia && fromWay.isFirstLastNode(lastNode)) {
357 viaNode = lastNode;
358 } else {
359 putError(r, tr("The \"from\" way does not start or end at the \"via\" way."), true);
360 return;
361 }
362 if(!toWay.isFirstLastNode(viaNode == firstNode ? lastNode : firstNode)) {
363 putError(r, tr("The \"to\" way does not start or end at the \"via\" way."), true);
364 }
365 }
366
367 /* find the "direct" nodes before the via node */
368 Node fromNode = null;
369 if(fromWay.firstNode() == via) {
370 fromNode = fromWay.getNode(1);
371 } else {
372 fromNode = fromWay.getNode(fromWay.getNodesCount()-2);
373 }
374
375 Point pFrom = nc.getPoint(fromNode);
376 Point pVia = nc.getPoint(viaNode);
377
378 /* starting from via, go back the "from" way a few pixels
379 (calculate the vector vx/vy with the specified length and the direction
380 away from the "via" node along the first segment of the "from" way)
381 */
382 double distanceFromVia=14;
383 double dx = (pFrom.x >= pVia.x) ? (pFrom.x - pVia.x) : (pVia.x - pFrom.x);
384 double dy = (pFrom.y >= pVia.y) ? (pFrom.y - pVia.y) : (pVia.y - pFrom.y);
385
386 double fromAngle;
387 if(dx == 0.0) {
388 fromAngle = Math.PI/2;
389 } else {
390 fromAngle = Math.atan(dy / dx);
391 }
392 double fromAngleDeg = Math.toDegrees(fromAngle);
393
394 double vx = distanceFromVia * Math.cos(fromAngle);
395 double vy = distanceFromVia * Math.sin(fromAngle);
396
397 if(pFrom.x < pVia.x) {
398 vx = -vx;
399 }
400 if(pFrom.y < pVia.y) {
401 vy = -vy;
402 }
403
404 /* go a few pixels away from the way (in a right angle)
405 (calculate the vx2/vy2 vector with the specified length and the direction
406 90degrees away from the first segment of the "from" way)
407 */
408 double distanceFromWay=10;
409 double vx2 = 0;
410 double vy2 = 0;
411 double iconAngle = 0;
412
413 if(pFrom.x >= pVia.x && pFrom.y >= pVia.y) {
414 if(!leftHandTraffic) {
415 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90));
416 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90));
417 } else {
418 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90));
419 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90));
420 }
421 iconAngle = 270+fromAngleDeg;
422 }
423 if(pFrom.x < pVia.x && pFrom.y >= pVia.y) {
424 if(!leftHandTraffic) {
425 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
426 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
427 } else {
428 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180));
429 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180));
430 }
431 iconAngle = 90-fromAngleDeg;
432 }
433 if(pFrom.x < pVia.x && pFrom.y < pVia.y) {
434 if(!leftHandTraffic) {
435 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90));
436 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90));
437 } else {
438 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90));
439 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90));
440 }
441 iconAngle = 90+fromAngleDeg;
442 }
443 if(pFrom.x >= pVia.x && pFrom.y < pVia.y) {
444 if(!leftHandTraffic) {
445 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180));
446 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180));
447 } else {
448 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
449 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
450 }
451 iconAngle = 270-fromAngleDeg;
452 }
453
454 IconElemStyle nodeStyle = getPrimitiveNodeStyle(r);
455
456 if (nodeStyle == null) {
457 putError(r, tr("Style for restriction {0} not found.", r.get("restriction")), true);
458 return;
459 }
460
461 painter.drawRestriction(inactive || r.isDisabled() ? nodeStyle.getDisabledIcon() : nodeStyle.icon,
462 pVia, vx, vx2, vy, vy2, iconAngle, data.isSelected(r));
463 }
464
465 public boolean drawMultipolygon(Relation r) {
466 boolean drawn = false;
467
468 Multipolygon multipolygon = new Multipolygon(nc);
469 multipolygon.load(r);
470
471 ElemStyle wayStyle = getPrimitiveStyle(r);
472
473 // If area style was not found for relation then use style of ways
474 if(styles != null && !(wayStyle instanceof AreaElemStyle)) {
475 for (Way w : multipolygon.getOuterWays()) {
476 wayStyle = styles.getArea(w);
477 if(wayStyle != null) {
478 break;
479 }
480 }
481 r.mappaintStyle = wayStyle;
482 }
483
484 if (wayStyle instanceof AreaElemStyle) {
485 boolean zoomok = isZoomOk(wayStyle);
486 boolean visible = false;
487
488 drawn = true;
489
490 if(zoomok && !multipolygon.getOuterWays().isEmpty()) {
491 AreaElemStyle areaStyle = (AreaElemStyle)wayStyle;
492 for (PolyData pd : multipolygon.getCombinedPolygons()) {
493 Polygon p = pd.get();
494 if(!isPolygonVisible(p)) {
495 continue;
496 }
497
498 boolean selected = pd.selected || data.isSelected(r);
499 painter.drawArea(p, selected ? paintSettings.getSelectedColor() : areaStyle.color, null);
500 visible = true;
501 }
502 }
503
504 if(!visible)
505 return drawn;
506 for (Way wInner : multipolygon.getInnerWays())
507 {
508 ElemStyle innerStyle = getPrimitiveStyle(wInner);
509 if(innerStyle == null)
510 {
511 if (data.isSelected(wInner)) {
512 continue;
513 }
514 if(zoomok && (wInner.mappaintDrawnCode != paintid || multipolygon.getOuterWays().isEmpty())) {
515 ((AreaElemStyle)wayStyle).getLineStyle().paintPrimitive(wInner, paintSettings, painter, (data.isSelected(wInner)
516 || data.isSelected(r)));
517 }
518 wInner.mappaintDrawnCode = paintid;
519 }
520 else
521 {
522 if(data.isSelected(r))
523 {
524 drawSelectedMember(wInner, innerStyle,
525 !wayStyle.equals(innerStyle), data.isSelected(wInner));
526 }
527 if(wayStyle.equals(innerStyle))
528 {
529 putError(r, tr("Style for inner way ''{0}'' equals multipolygon.",
530 wInner.getDisplayName(DefaultNameFormatter.getInstance())), false);
531 if(!data.isSelected(r)) {
532 wInner.mappaintDrawnAreaCode = paintid;
533 }
534 }
535 }
536 }
537 for (Way wOuter : multipolygon.getOuterWays())
538 {
539 ElemStyle outerStyle = getPrimitiveStyle(wOuter);
540 if(outerStyle == null)
541 {
542 // Selected ways are drawn at the very end
543 if (data.isSelected(wOuter)) {
544 continue;
545 }
546 if(zoomok)
547 {
548 ((AreaElemStyle)wayStyle).getLineStyle().paintPrimitive(wOuter, paintSettings, painter, (data.isSelected(wOuter) || data.isSelected(r)));
549 }
550 wOuter.mappaintDrawnCode = paintid;
551 }
552 else
553 {
554 if(outerStyle instanceof AreaElemStyle
555 && !wayStyle.equals(outerStyle))
556 {
557 putError(r, tr("Style for outer way ''{0}'' mismatches.",
558 wOuter.getDisplayName(DefaultNameFormatter.getInstance())), true);
559 }
560 if(data.isSelected(r))
561 {
562 drawSelectedMember(wOuter, outerStyle, false, false);
563 }
564 else if(outerStyle instanceof AreaElemStyle) {
565 wOuter.mappaintDrawnAreaCode = paintid;
566 }
567 }
568 }
569 }
570 return drawn;
571 }
572
573 protected boolean isPolygonVisible(Polygon polygon) {
574 Rectangle bounds = polygon.getBounds();
575 if (bounds.width == 0 && bounds.height == 0) return false;
576 if (bounds.x > nc.getWidth()) return false;
577 if (bounds.y > nc.getHeight()) return false;
578 if (bounds.x + bounds.width < 0) return false;
579 if (bounds.y + bounds.height < 0) return false;
580 return true;
581 }
582
583 protected Polygon getPolygon(Way w)
584 {
585 Polygon polygon = new Polygon();
586
587 for (Node n : w.getNodes())
588 {
589 Point p = nc.getPoint(n);
590 polygon.addPoint(p.x,p.y);
591 }
592 return polygon;
593 }
594
595 protected Point2D getCentroid(Polygon p)
596 {
597 double cx = 0.0, cy = 0.0, a = 0.0;
598
599 // usually requires points[0] == points[npoints] and can then use i+1 instead of j.
600 // Faked it slowly using j. If this is really gets used, this should be fixed.
601 for (int i = 0; i < p.npoints; i++) {
602 int j = i+1 == p.npoints ? 0 : i+1;
603 a += (p.xpoints[i] * p.ypoints[j]) - (p.ypoints[i] * p.xpoints[j]);
604 cx += (p.xpoints[i] + p.xpoints[j]) * (p.xpoints[i] * p.ypoints[j] - p.ypoints[i] * p.xpoints[j]);
605 cy += (p.ypoints[i] + p.ypoints[j]) * (p.xpoints[i] * p.ypoints[j] - p.ypoints[i] * p.xpoints[j]);
606 }
607 return new Point2D.Double(cx / (3.0*a), cy / (3.0*a));
608 }
609
610 protected double getArea(Polygon p)
611 {
612 double sum = 0.0;
613
614 // usually requires points[0] == points[npoints] and can then use i+1 instead of j.
615 // Faked it slowly using j. If this is really gets used, this should be fixed.
616 for (int i = 0; i < p.npoints; i++) {
617 int j = i+1 == p.npoints ? 0 : i+1;
618 sum = sum + (p.xpoints[i] * p.ypoints[j]) - (p.ypoints[i] * p.xpoints[j]);
619 }
620 return Math.abs(sum/2.0);
621 }
622
623 DataSet data;
624
625 <T extends OsmPrimitive> Collection<T> selectedLast(final DataSet data, Collection <T> prims) {
626 ArrayList<T> sorted = new ArrayList<T>(prims);
627 Collections.sort(sorted,
628 new Comparator<T>() {
629 public int compare(T o1, T o2) {
630 boolean s1 = data.isSelected(o1);
631 boolean s2 = data.isSelected(o2);
632 if (s1 && !s2)
633 return 1;
634 if (!s1 && s2)
635 return -1;
636 return o1.compareTo(o2);
637 }
638 });
639 return sorted;
640 }
641
642 /* Shows areas before non-areas */
643 public void visitAll(DataSet data, boolean virtual, Bounds bounds) {
644 BBox bbox = new BBox(bounds);
645 this.data = data;
646 ++paintid;
647
648 useStyleCache = Main.pref.getBoolean("mappaint.cache", true);
649 int fillAreas = Main.pref.getInteger("mappaint.fillareas", 10000000);
650 LatLon ll1 = nc.getLatLon(0, 0);
651 LatLon ll2 = nc.getLatLon(100, 0);
652 dist = ll1.greatCircleDistance(ll2);
653
654 zoomLevelDisplay = Main.pref.getBoolean("mappaint.zoomLevelDisplay", false);
655 circum = nc.getDist100Pixel();
656 styles = MapPaintStyles.getStyles().getStyleSet();
657 drawMultipolygon = Main.pref.getBoolean("mappaint.multipolygon", true);
658 drawRestriction = Main.pref.getBoolean("mappaint.restriction", true);
659 leftHandTraffic = Main.pref.getBoolean("mappaint.lefthandtraffic", false);
660 minEN = nc.getEastNorth(0, nc.getHeight() - 1);
661 maxEN = nc.getEastNorth(nc.getWidth() - 1, 0);
662
663 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
664 Main.pref.getBoolean("mappaint.use-antialiasing", false) ?
665 RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
666
667 this.paintSettings = MapPaintSettings.INSTANCE;
668 this.painter = new MapPainter(paintSettings, g, inactive, nc, virtual, dist, circum);
669
670 data.clearErrors();
671
672
673 if (fillAreas > dist && styles != null && styles.hasAreas()) {
674 Collection<Way> noAreaWays = new LinkedList<Way>();
675
676 /*** RELATIONS ***/
677 for (final Relation osm: data.searchRelations(bbox)) {
678 if (osm.isDrawable()) {
679 paintUnselectedRelation(osm);
680 }
681 }
682
683 /*** AREAS ***/
684 for (final Way osm : selectedLast(data, data.searchWays(bbox))) {
685 if (osm.isDrawable() && osm.mappaintDrawnCode != paintid) {
686 if (isPrimitiveArea(osm) && osm.mappaintDrawnAreaCode != paintid) {
687 drawWay(osm, fillAreas);
688 } else {
689 noAreaWays.add(osm);
690 }
691 }
692 }
693
694 /*** WAYS ***/
695 for (final Way osm : noAreaWays) {
696 drawWay(osm, 0);
697 }
698 } else {
699 drawMultipolygon = false;
700
701 /*** RELATIONS ***/
702 for (final Relation osm: data.searchRelations(bbox)) {
703 if (osm.isDrawable()) {
704 paintUnselectedRelation(osm);
705 }
706 }
707
708 /*** WAYS (filling disabled) ***/
709 for (final Way way: data.searchWays(bbox)) {
710 if (way.isDrawable() && !data.isSelected(way)) {
711 drawWay(way, 0);
712 }
713 }
714 }
715
716 /*** SELECTED ***/
717 for (final OsmPrimitive osm : data.getSelected()) {
718 if (osm.isUsable() && !(osm instanceof Node) && osm.mappaintDrawnCode != paintid) {
719 osm.visit(new AbstractVisitor() {
720 public void visit(Way w) {
721 drawWay(w, 0);
722 }
723
724 public void visit(Node n) {
725 // Selected nodes are painted in following part
726 }
727
728 public void visit(Relation r) {
729 /* TODO: is it possible to do this like the nodes/ways code? */
730 // Only nodes are painted, ways was already painted before (this might cause that
731 // way in selected relation is hidden by another way)
732 for (RelationMember m : r.getMembers()) {
733 if (m.isNode() && m.getMember().isDrawable()) {
734 drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true);
735 }
736 }
737 }
738 });
739 }
740 }
741
742 /*** NODES ***/
743 for (final Node osm: data.searchNodes(bbox)) {
744 if (!osm.isIncomplete() && !osm.isDeleted() && (data.isSelected(osm) || !osm.isFiltered())
745 && osm.mappaintDrawnCode != paintid) {
746 drawNode(osm);
747 }
748 }
749
750 painter.drawVirtualNodes(data.searchWays(bbox));
751 }
752
753 public void putError(OsmPrimitive p, String text, boolean isError)
754 {
755 data.addError(p, isError ? tr("Error: {0}", text) : tr("Warning: {0}", text));
756 }
757
758 public void setGraphics(Graphics2D g) {
759 this.g = g;
760 }
761
762 public void setInactive(boolean inactive) {
763 this.inactive = inactive;
764 }
765
766 public void setNavigatableComponent(NavigatableComponent nc) {
767 this.nc = nc;
768 }
769}
Note: See TracBrowser for help on using the repository browser.