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

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

Move most of multipolygon handling from MapPaintVisitor to the new Multipolygon class, move checks to validator plugin

  • Property svn:eol-style set to native
File size: 27.8 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 Way fromWay = null;
247 Way toWay = null;
248 OsmPrimitive via = null;
249
250 /* find the "from", "via" and "to" elements */
251 for (RelationMember m : r.getMembers())
252 {
253 if(m.getMember().isIncomplete())
254 return;
255 else
256 {
257 if(m.isWay())
258 {
259 Way w = m.getWay();
260 if(w.getNodesCount() < 2) {
261 continue;
262 }
263
264 if("from".equals(m.getRole())) {
265 if(fromWay != null) {
266 putError(r, tr("More than one \"from\" way found."), true);
267 } else {
268 fromWay = w;
269 }
270 } else if("to".equals(m.getRole())) {
271 if(toWay != null) {
272 putError(r, tr("More than one \"to\" way found."), true);
273 } else {
274 toWay = w;
275 }
276 } else if("via".equals(m.getRole())) {
277 if(via != null) {
278 putError(r, tr("More than one \"via\" found."), true);
279 } else {
280 via = w;
281 }
282 } else {
283 putError(r, tr("Unknown role ''{0}''.", m.getRole()), true);
284 }
285 }
286 else if(m.isNode())
287 {
288 Node n = m.getNode();
289 if("via".equals(m.getRole()))
290 {
291 if(via != null) {
292 putError(r, tr("More than one \"via\" found."), true);
293 } else {
294 via = n;
295 }
296 } else {
297 putError(r, tr("Unknown role ''{0}''.", m.getRole()), true);
298 }
299 } else {
300 putError(r, tr("Unknown member type for ''{0}''.", m.getMember().getDisplayName(DefaultNameFormatter.getInstance())), true);
301 }
302 }
303 }
304
305 if (fromWay == null) {
306 putError(r, tr("No \"from\" way found."), true);
307 return;
308 }
309 if (toWay == null) {
310 putError(r, tr("No \"to\" way found."), true);
311 return;
312 }
313 if (via == null) {
314 putError(r, tr("No \"via\" node or way found."), true);
315 return;
316 }
317
318 Node viaNode;
319 if(via instanceof Node)
320 {
321 viaNode = (Node) via;
322 if(!fromWay.isFirstLastNode(viaNode)) {
323 putError(r, tr("The \"from\" way doesn't start or end at a \"via\" node."), true);
324 return;
325 }
326 if(!toWay.isFirstLastNode(viaNode)) {
327 putError(r, tr("The \"to\" way doesn't start or end at a \"via\" node."), true);
328 }
329 }
330 else
331 {
332 Way viaWay = (Way) via;
333 Node firstNode = viaWay.firstNode();
334 Node lastNode = viaWay.lastNode();
335 boolean onewayvia = false;
336
337 String onewayviastr = viaWay.get("oneway");
338 if(onewayviastr != null)
339 {
340 if("-1".equals(onewayviastr)) {
341 onewayvia = true;
342 Node tmp = firstNode;
343 firstNode = lastNode;
344 lastNode = tmp;
345 } else {
346 onewayvia = OsmUtils.getOsmBoolean(onewayviastr);
347 }
348 }
349
350 if(fromWay.isFirstLastNode(firstNode)) {
351 viaNode = firstNode;
352 } else if (!onewayvia && fromWay.isFirstLastNode(lastNode)) {
353 viaNode = lastNode;
354 } else {
355 putError(r, tr("The \"from\" way doesn't start or end at the \"via\" way."), true);
356 return;
357 }
358 if(!toWay.isFirstLastNode(viaNode == firstNode ? lastNode : firstNode)) {
359 putError(r, tr("The \"to\" way doesn't start or end at the \"via\" way."), true);
360 }
361 }
362
363 /* find the "direct" nodes before the via node */
364 Node fromNode = null;
365 if(fromWay.firstNode() == via) {
366 fromNode = fromWay.getNode(1);
367 } else {
368 fromNode = fromWay.getNode(fromWay.getNodesCount()-2);
369 }
370
371 Point pFrom = nc.getPoint(fromNode);
372 Point pVia = nc.getPoint(viaNode);
373
374 /* starting from via, go back the "from" way a few pixels
375 (calculate the vector vx/vy with the specified length and the direction
376 away from the "via" node along the first segment of the "from" way)
377 */
378 double distanceFromVia=14;
379 double dx = (pFrom.x >= pVia.x) ? (pFrom.x - pVia.x) : (pVia.x - pFrom.x);
380 double dy = (pFrom.y >= pVia.y) ? (pFrom.y - pVia.y) : (pVia.y - pFrom.y);
381
382 double fromAngle;
383 if(dx == 0.0) {
384 fromAngle = Math.PI/2;
385 } else {
386 fromAngle = Math.atan(dy / dx);
387 }
388 double fromAngleDeg = Math.toDegrees(fromAngle);
389
390 double vx = distanceFromVia * Math.cos(fromAngle);
391 double vy = distanceFromVia * Math.sin(fromAngle);
392
393 if(pFrom.x < pVia.x) {
394 vx = -vx;
395 }
396 if(pFrom.y < pVia.y) {
397 vy = -vy;
398 }
399
400 /* go a few pixels away from the way (in a right angle)
401 (calculate the vx2/vy2 vector with the specified length and the direction
402 90degrees away from the first segment of the "from" way)
403 */
404 double distanceFromWay=10;
405 double vx2 = 0;
406 double vy2 = 0;
407 double iconAngle = 0;
408
409 if(pFrom.x >= pVia.x && pFrom.y >= pVia.y) {
410 if(!leftHandTraffic) {
411 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90));
412 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90));
413 } else {
414 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90));
415 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90));
416 }
417 iconAngle = 270+fromAngleDeg;
418 }
419 if(pFrom.x < pVia.x && pFrom.y >= pVia.y) {
420 if(!leftHandTraffic) {
421 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
422 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
423 } else {
424 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180));
425 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180));
426 }
427 iconAngle = 90-fromAngleDeg;
428 }
429 if(pFrom.x < pVia.x && pFrom.y < pVia.y) {
430 if(!leftHandTraffic) {
431 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 90));
432 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 90));
433 } else {
434 vx2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg - 90));
435 vy2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg - 90));
436 }
437 iconAngle = 90+fromAngleDeg;
438 }
439 if(pFrom.x >= pVia.x && pFrom.y < pVia.y) {
440 if(!leftHandTraffic) {
441 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg + 180));
442 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg + 180));
443 } else {
444 vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
445 vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
446 }
447 iconAngle = 270-fromAngleDeg;
448 }
449
450 IconElemStyle nodeStyle = getPrimitiveNodeStyle(r);
451
452 if (nodeStyle == null) {
453 putError(r, tr("Style for restriction {0} not found.", r.get("restriction")), true);
454 return;
455 }
456
457 painter.drawRestriction(inactive || r.isDisabled() ? nodeStyle.getDisabledIcon() : nodeStyle.icon,
458 pVia, vx, vx2, vy, vy2, iconAngle, data.isSelected(r));
459 }
460
461 public boolean drawMultipolygon(Relation r) {
462 boolean drawn = false;
463
464 Multipolygon multipolygon = new Multipolygon(nc);
465 multipolygon.load(r);
466
467 ElemStyle wayStyle = getPrimitiveStyle(r);
468
469 // If area style was not found for relation then use style of ways
470 if(styles != null && !(wayStyle instanceof AreaElemStyle)) {
471 for (Way w : multipolygon.getOuterWays()) {
472 wayStyle = styles.getArea(w);
473 if(wayStyle != null) {
474 break;
475 }
476 }
477 r.mappaintStyle = wayStyle;
478 }
479
480 if (wayStyle instanceof AreaElemStyle) {
481 boolean zoomok = isZoomOk(wayStyle);
482 boolean visible = false;
483
484 drawn = true;
485
486 if(zoomok && !multipolygon.getOuterWays().isEmpty()) {
487 AreaElemStyle areaStyle = (AreaElemStyle)wayStyle;
488 for (PolyData pd : multipolygon.getCombinedPolygons()) {
489 Polygon p = pd.get();
490 if(!isPolygonVisible(p)) {
491 continue;
492 }
493
494 boolean selected = pd.selected || data.isSelected(r);
495 painter.drawArea(p, selected ? paintSettings.getSelectedColor() : areaStyle.color, null);
496 visible = true;
497 }
498 }
499
500 if(!visible)
501 return drawn;
502 for (Way wInner : multipolygon.getInnerWays())
503 {
504 ElemStyle innerStyle = getPrimitiveStyle(wInner);
505 if(innerStyle == null)
506 {
507 if (data.isSelected(wInner)) {
508 continue;
509 }
510 if(zoomok && (wInner.mappaintDrawnCode != paintid || multipolygon.getOuterWays().isEmpty())) {
511 ((AreaElemStyle)wayStyle).getLineStyle().paintPrimitive(wInner, paintSettings, painter, (data.isSelected(wInner)
512 || data.isSelected(r)));
513 }
514 wInner.mappaintDrawnCode = paintid;
515 }
516 else
517 {
518 if(data.isSelected(r))
519 {
520 drawSelectedMember(wInner, innerStyle,
521 !wayStyle.equals(innerStyle), data.isSelected(wInner));
522 }
523 if(wayStyle.equals(innerStyle))
524 {
525 putError(r, tr("Style for inner way ''{0}'' equals multipolygon.",
526 wInner.getDisplayName(DefaultNameFormatter.getInstance())), false);
527 if(!data.isSelected(r)) {
528 wInner.mappaintDrawnAreaCode = paintid;
529 }
530 }
531 }
532 }
533 for (Way wOuter : multipolygon.getOuterWays())
534 {
535 ElemStyle outerStyle = getPrimitiveStyle(wOuter);
536 if(outerStyle == null)
537 {
538 // Selected ways are drawn at the very end
539 if (data.isSelected(wOuter)) {
540 continue;
541 }
542 if(zoomok)
543 {
544 ((AreaElemStyle)wayStyle).getLineStyle().paintPrimitive(wOuter, paintSettings, painter, (data.isSelected(wOuter) || data.isSelected(r)));
545 }
546 wOuter.mappaintDrawnCode = paintid;
547 }
548 else
549 {
550 if(outerStyle instanceof AreaElemStyle
551 && !wayStyle.equals(outerStyle))
552 {
553 putError(r, tr("Style for outer way ''{0}'' mismatches.",
554 wOuter.getDisplayName(DefaultNameFormatter.getInstance())), true);
555 }
556 if(data.isSelected(r))
557 {
558 drawSelectedMember(wOuter, outerStyle, false, false);
559 }
560 else if(outerStyle instanceof AreaElemStyle) {
561 wOuter.mappaintDrawnAreaCode = paintid;
562 }
563 }
564 }
565 }
566 return drawn;
567 }
568
569 protected boolean isPolygonVisible(Polygon polygon) {
570 Rectangle bounds = polygon.getBounds();
571 if (bounds.width == 0 && bounds.height == 0) return false;
572 if (bounds.x > nc.getWidth()) return false;
573 if (bounds.y > nc.getHeight()) return false;
574 if (bounds.x + bounds.width < 0) return false;
575 if (bounds.y + bounds.height < 0) return false;
576 return true;
577 }
578
579 protected Polygon getPolygon(Way w)
580 {
581 Polygon polygon = new Polygon();
582
583 for (Node n : w.getNodes())
584 {
585 Point p = nc.getPoint(n);
586 polygon.addPoint(p.x,p.y);
587 }
588 return polygon;
589 }
590
591 protected Point2D getCentroid(Polygon p)
592 {
593 double cx = 0.0, cy = 0.0, a = 0.0;
594
595 // usually requires points[0] == points[npoints] and can then use i+1 instead of j.
596 // Faked it slowly using j. If this is really gets used, this should be fixed.
597 for (int i = 0; i < p.npoints; i++) {
598 int j = i+1 == p.npoints ? 0 : i+1;
599 a += (p.xpoints[i] * p.ypoints[j]) - (p.ypoints[i] * p.xpoints[j]);
600 cx += (p.xpoints[i] + p.xpoints[j]) * (p.xpoints[i] * p.ypoints[j] - p.ypoints[i] * p.xpoints[j]);
601 cy += (p.ypoints[i] + p.ypoints[j]) * (p.xpoints[i] * p.ypoints[j] - p.ypoints[i] * p.xpoints[j]);
602 }
603 return new Point2D.Double(cx / (3.0*a), cy / (3.0*a));
604 }
605
606 protected double getArea(Polygon p)
607 {
608 double sum = 0.0;
609
610 // usually requires points[0] == points[npoints] and can then use i+1 instead of j.
611 // Faked it slowly using j. If this is really gets used, this should be fixed.
612 for (int i = 0; i < p.npoints; i++) {
613 int j = i+1 == p.npoints ? 0 : i+1;
614 sum = sum + (p.xpoints[i] * p.ypoints[j]) - (p.ypoints[i] * p.xpoints[j]);
615 }
616 return Math.abs(sum/2.0);
617 }
618
619 DataSet data;
620
621 <T extends OsmPrimitive> Collection<T> selectedLast(final DataSet data, Collection <T> prims) {
622 ArrayList<T> sorted = new ArrayList<T>(prims);
623 Collections.sort(sorted,
624 new Comparator<T>() {
625 public int compare(T o1, T o2) {
626 boolean s1 = data.isSelected(o1);
627 boolean s2 = data.isSelected(o2);
628 if (s1 && !s2)
629 return 1;
630 if (!s1 && s2)
631 return -1;
632 return o1.compareTo(o2);
633 }
634 });
635 return sorted;
636 }
637
638 /* Shows areas before non-areas */
639 public void visitAll(DataSet data, boolean virtual, Bounds bounds) {
640 BBox bbox = new BBox(bounds);
641 this.data = data;
642
643 useStyleCache = Main.pref.getBoolean("mappaint.cache", true);
644 int fillAreas = Main.pref.getInteger("mappaint.fillareas", 10000000);
645 LatLon ll1 = nc.getLatLon(0, 0);
646 LatLon ll2 = nc.getLatLon(100, 0);
647 dist = ll1.greatCircleDistance(ll2);
648
649 zoomLevelDisplay = Main.pref.getBoolean("mappaint.zoomLevelDisplay", false);
650 circum = Main.map.mapView.getDist100Pixel();
651 styles = MapPaintStyles.getStyles().getStyleSet();
652 drawMultipolygon = Main.pref.getBoolean("mappaint.multipolygon", true);
653 drawRestriction = Main.pref.getBoolean("mappaint.restriction", true);
654 leftHandTraffic = Main.pref.getBoolean("mappaint.lefthandtraffic", false);
655 minEN = nc.getEastNorth(0, nc.getHeight() - 1);
656 maxEN = nc.getEastNorth(nc.getWidth() - 1, 0);
657
658 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
659 Main.pref.getBoolean("mappaint.use-antialiasing", false) ?
660 RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
661
662 this.paintSettings = MapPaintSettings.INSTANCE;
663 this.painter = new MapPainter(paintSettings, g, inactive, nc, virtual, dist, circum);
664
665 data.clearErrors();
666
667 ++paintid;
668
669 if (fillAreas > dist && styles != null && styles.hasAreas()) {
670 Collection<Way> noAreaWays = new LinkedList<Way>();
671
672 /*** RELATIONS ***/
673 for (final Relation osm: data.getRelations()) {
674 if (osm.isDrawable()) {
675 paintUnselectedRelation(osm);
676 }
677 }
678
679 /*** AREAS ***/
680 for (final Way osm : selectedLast(data, data.searchWays(bbox))) {
681 if (osm.isDrawable() && osm.mappaintDrawnCode != paintid) {
682 if (isPrimitiveArea(osm) && osm.mappaintDrawnAreaCode != paintid) {
683 drawWay(osm, fillAreas);
684 } else {
685 noAreaWays.add(osm);
686 }
687 }
688 }
689
690 /*** WAYS ***/
691 for (final Way osm : noAreaWays) {
692 drawWay(osm, 0);
693 }
694 } else {
695 drawMultipolygon = false;
696
697 /*** RELATIONS ***/
698 for (final Relation osm: data.getRelations()) {
699 if (osm.isDrawable()) {
700 paintUnselectedRelation(osm);
701 }
702 }
703
704 /*** WAYS (filling disabled) ***/
705 for (final Way way: data.getWays()) {
706 if (way.isDrawable() && !data.isSelected(way)) {
707 drawWay(way, 0);
708 }
709 }
710 }
711
712 /*** SELECTED ***/
713 for (final OsmPrimitive osm : data.getSelected()) {
714 if (osm.isUsable() && !(osm instanceof Node) && osm.mappaintDrawnCode != paintid) {
715 osm.visit(new AbstractVisitor() {
716 public void visit(Way w) {
717 drawWay(w, 0);
718 }
719
720 public void visit(Node n) {
721 // Selected nodes are painted in following part
722 }
723
724 public void visit(Relation r) {
725 /* TODO: is it possible to do this like the nodes/ways code? */
726 // Only nodes are painted, ways was already painted before (this might cause that
727 // way in selected relation is hidden by another way)
728 for (RelationMember m : r.getMembers()) {
729 if (m.isNode() && m.getMember().isDrawable()) {
730 drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true);
731 }
732 }
733 }
734 });
735 }
736 }
737
738 /*** NODES ***/
739 for (final Node osm: data.searchNodes(bbox)) {
740 if (!osm.isIncomplete() && !osm.isDeleted() && (data.isSelected(osm) || !osm.isFiltered())
741 && osm.mappaintDrawnCode != paintid) {
742 drawNode(osm);
743 }
744 }
745
746 painter.drawVirtualNodes(data.searchWays(bbox));
747 }
748
749 public void putError(OsmPrimitive p, String text, boolean isError)
750 {
751 data.addError(p, isError ? tr("Error: {0}", text) : tr("Warning: {0}", text));
752 }
753
754 public void setGraphics(Graphics2D g) {
755 this.g = g;
756 }
757
758 public void setInactive(boolean inactive) {
759 this.inactive = inactive;
760 }
761
762 public void setNavigatableComponent(NavigatableComponent nc) {
763 this.nc = nc;
764 }
765}
Note: See TracBrowser for help on using the repository browser.