Ticket #3781: rework-multipolygons-0.patch
| File rework-multipolygons-0.patch, 22.2 KB (added by , 17 years ago) |
|---|
-
src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
26 26 import java.util.Iterator; 27 27 import java.util.LinkedList; 28 28 import java.util.List; 29 import java.util.TreeSet; 30 import java.util.Comparator; 29 31 30 32 import javax.swing.ImageIcon; 31 33 … … 52 54 public class MapPaintVisitor extends SimplePaintVisitor { 53 55 protected boolean useRealWidth; 54 56 protected boolean zoomLevelDisplay; 55 protected int fillAreas;56 57 protected boolean drawMultipolygon; 57 58 protected boolean drawRestriction; 58 59 protected boolean leftHandTraffic; … … 73 74 protected double circum; 74 75 protected double dist; 75 76 protected Collection<String> regionalNameOrder; 76 protected Boolean selectedCall;77 77 protected Boolean useStyleCache; 78 78 private static int paintid = 0; 79 79 private static int viewid = 0; … … 139 139 * @param n The node to draw. 140 140 */ 141 141 @Override 142 public void visit(Node n) { 142 public void visit(Node n) {} 143 public void drawNode(Node n) { 143 144 /* check, if the node is visible at all */ 144 145 if((n.getEastNorth().east() > maxEN.east() ) || 145 146 (n.getEastNorth().north() > maxEN.north()) || … … 175 176 * Draw a line for all segments, according to tags. 176 177 * @param w The way to draw. 177 178 */ 178 @Override 179 public void visit(Way w) { 179 @Override 180 public void visit(Way w) {} 181 public void drawWay(Way w, int fillAreas) { 180 182 if(w.getNodesCount() < 2) 181 183 { 182 184 w.mappaintVisibleCode = viewid; … … 390 392 displaySegments(); 391 393 } 392 394 393 public Collection< Way> joinWays(Collection<Way> join, OsmPrimitive errs)395 public Collection<PolyData> joinWays(Collection<Way> join, OsmPrimitive errs) 394 396 { 395 Collection< Way> res = new LinkedList<Way>();397 Collection<PolyData> res = new LinkedList<PolyData>(); 396 398 Object[] joinArray = join.toArray(); 397 399 int left = join.size(); 398 400 while(left != 0) … … 479 481 { 480 482 w = new Way(w); 481 483 w.setNodes(n); 482 if (selected) { 483 data.addSelected(Collections.singleton(w),false /* don't notify listeners */); 484 } else { 485 data.clearSelection(w); 486 } 484 // Do not mess with the DataSet's contents here. 487 485 } 488 486 if(!w.isClosed()) 489 487 { … … 493 491 w.getDisplayName(DefaultNameFormatter.getInstance())), true); 494 492 } 495 493 } 496 res.add(w); 494 PolyData pd = new PolyData(w); 495 pd.selected = selected; 496 res.add(pd); 497 497 } /* while(left != 0) */ 498 498 499 499 return res; … … 530 530 osm.mappaintDrawnCode = paintid; 531 531 } 532 532 533 @Override 534 public void visit(Relation r) { 535 533 public void visit(Relation r) {}; 534 public void paintUnselectedRelation(Relation r) { 536 535 r.mappaintVisibleCode = 0; 537 536 538 /* TODO: is it possible to do this like the nodes/ways code? */ 539 //if(profilerOmitDraw) 540 // return; 541 542 if(selectedCall) 537 if (drawMultipolygon && "multipolygon".equals(r.get("type"))) 543 538 { 544 for (RelationMember m : r.getMembers())545 {546 if (m.isNode() && !m.getMember().incomplete && !m.getMember().isDeleted() && !m.getMember().isFiltered())547 {548 drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true);549 }550 }551 return;552 }553 else if (drawMultipolygon && "multipolygon".equals(r.get("type")))554 {555 539 if(drawMultipolygon(r)) 556 540 return; 557 541 } … … 564 548 { 565 549 for (RelationMember m : r.getMembers()) 566 550 { 567 if (m.isWay() && !m.getMember().incomplete && !m.getMember().isDeleted()) /* nodes drawn on second call */551 if (m.isWay() && drawable(m.getMember())) 568 552 { 569 553 drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) 570 554 : null, true, true); … … 844 828 } 845 829 } 846 830 831 class PolyData { 832 public Polygon poly = new Polygon(); 833 public Way way; 834 public boolean selected = false; 835 private Point p = null; 836 private Collection<Polygon> inner = null; 837 PolyData(Way w) 838 { 839 way = w; 840 for (Node n : w.getNodes()) 841 { 842 p = nc.getPoint(n); 843 poly.addPoint(p.x,p.y); 844 } 845 } 846 public int contains(Polygon p) 847 { 848 int contains = p.npoints; 849 for(int i = 0; i < p.npoints; ++i) 850 { 851 if(poly.contains(p.xpoints[i],p.ypoints[i])) { 852 --contains; 853 } 854 } 855 if(contains == 0) return 1; 856 if(contains == p.npoints) return 0; 857 return 2; 858 } 859 public void addInner(Polygon p) 860 { 861 if(inner == null) { 862 inner = new ArrayList<Polygon>(); 863 } 864 inner.add(p); 865 } 866 public boolean isClosed() 867 { 868 return (poly.npoints >= 3 869 && poly.xpoints[0] == poly.xpoints[poly.npoints-1] 870 && poly.ypoints[0] == poly.ypoints[poly.npoints-1]); 871 } 872 public Polygon get() 873 { 874 if(inner != null) 875 { 876 for (Polygon pp : inner) 877 { 878 for(int i = 0; i < pp.npoints; ++i) { 879 poly.addPoint(pp.xpoints[i],pp.ypoints[i]); 880 } 881 poly.addPoint(p.x,p.y); 882 } 883 inner = null; 884 } 885 return poly; 886 } 887 } 888 void addInnerToOuters(Relation r, boolean incomplete, PolyData pdInner, LinkedList<PolyData> outerPolygons) 889 { 890 Way wInner = pdInner.way; 891 if(wInner != null && !wInner.isClosed()) 892 { 893 Point pInner = nc.getPoint(wInner.getNode(0)); 894 pdInner.poly.addPoint(pInner.x,pInner.y); 895 } 896 PolyData o = null; 897 for (PolyData pdOuter : outerPolygons) 898 { 899 Integer c = pdOuter.contains(pdInner.poly); 900 if(c >= 1) 901 { 902 if(c > 1 && pdOuter.way != null && pdOuter.way.isClosed()) 903 { 904 r.putError(tr("Intersection between ways ''{0}'' and ''{1}''.", 905 pdOuter.way.getDisplayName(DefaultNameFormatter.getInstance()), wInner.getDisplayName(DefaultNameFormatter.getInstance())), true); 906 } 907 if(o == null || o.contains(pdOuter.poly) > 0) { 908 o = pdOuter; 909 } 910 } 911 } 912 if(o == null) 913 { 914 if(!incomplete) 915 { 916 r.putError(tr("Inner way ''{0}'' is outside.", 917 wInner.getDisplayName(DefaultNameFormatter.getInstance())), true); 918 } 919 o = outerPolygons.get(0); 920 } 921 o.addInner(pdInner.poly); 922 } 923 847 924 public Boolean drawMultipolygon(Relation r) { 848 925 Collection<Way> inner = new LinkedList<Way>(); 849 926 Collection<Way> outer = new LinkedList<Way>(); … … 861 938 m.getMember().getDisplayName(DefaultNameFormatter.getInstance())), true); 862 939 } else if(m.getMember().incomplete) { 863 940 incomplete = true; 864 } else 865 { 866 if(m.isWay()) 867 { 941 } else { 942 if(m.isWay()) { 868 943 Way w = m.getWay(); 869 if(w.getNodesCount() < 2) 870 { 944 if(w.getNodesCount() < 2) { 871 945 r.putError(tr("Way ''{0}'' with less than two points.", 872 946 w.getDisplayName(DefaultNameFormatter.getInstance())), true); 873 947 } … … 875 949 inner.add(w); 876 950 } else if("outer".equals(m.getRole())) { 877 951 outer.add(w); 878 } else 879 { 952 } else { 880 953 r.putError(tr("No useful role ''{0}'' for Way ''{1}''.", 881 954 m.getRole(), w.getDisplayName(DefaultNameFormatter.getInstance())), true); 882 955 if(!m.hasRole()) { … … 911 984 { 912 985 Boolean zoomok = isZoomOk(wayStyle); 913 986 Boolean visible = false; 914 Collection<Way> join = new LinkedList<Way>(); 987 Collection<Way> outerjoin = new LinkedList<Way>(); 988 Collection<Way> innerjoin = new LinkedList<Way>(); 915 989 916 990 drawn = true; 917 991 for (Way w : outer) … … 919 993 if(w.isClosed()) { 920 994 outerclosed.add(w); 921 995 } else { 922 join.add(w);996 outerjoin.add(w); 923 997 } 924 998 } 925 if(join.size() != 0)926 {927 for(Way w : joinWays(join, incomplete ? null : r)) {928 outerclosed.add(w);929 }930 }931 932 join.clear();933 999 for (Way w : inner) 934 1000 { 935 1001 if(w.isClosed()) { 936 1002 innerclosed.add(w); 937 1003 } else { 938 join.add(w);1004 innerjoin.add(w); 939 1005 } 940 1006 } 941 if( join.size() != 0)1007 if(outerclosed.size() == 0 && outerjoin.size() == 0) 942 1008 { 943 for(Way w : joinWays(join, incomplete ? null : r)) {944 innerclosed.add(w);945 }946 }947 948 if(outerclosed.size() == 0)949 {950 1009 r.putError(tr("No outer way for multipolygon ''{0}''.", 951 1010 r.getDisplayName(DefaultNameFormatter.getInstance())), true); 952 1011 visible = true; /* prevent killing remaining ways */ 953 1012 } 954 1013 else if(zoomok) 955 1014 { 956 class PolyData { 957 public Polygon poly = new Polygon(); 958 public Way way; 959 private Point p = null; 960 private Collection<Polygon> inner = null; 961 PolyData(Way w) 962 { 963 way = w; 964 for (Node n : w.getNodes()) 965 { 966 p = nc.getPoint(n); 967 poly.addPoint(p.x,p.y); 968 } 969 } 970 public int contains(Polygon p) 971 { 972 int contains = p.npoints; 973 for(int i = 0; i < p.npoints; ++i) 974 { 975 if(poly.contains(p.xpoints[i],p.ypoints[i])) { 976 --contains; 977 } 978 } 979 if(contains == 0) return 1; 980 if(contains == p.npoints) return 0; 981 return 2; 982 } 983 public void addInner(Polygon p) 984 { 985 if(inner == null) { 986 inner = new ArrayList<Polygon>(); 987 } 988 inner.add(p); 989 } 990 public boolean isClosed() 991 { 992 return (poly.npoints >= 3 993 && poly.xpoints[0] == poly.xpoints[poly.npoints-1] 994 && poly.ypoints[0] == poly.ypoints[poly.npoints-1]); 995 } 996 public Polygon get() 997 { 998 if(inner != null) 999 { 1000 for (Polygon pp : inner) 1001 { 1002 for(int i = 0; i < pp.npoints; ++i) { 1003 poly.addPoint(pp.xpoints[i],pp.ypoints[i]); 1004 } 1005 poly.addPoint(p.x,p.y); 1006 } 1007 inner = null; 1008 } 1009 return poly; 1010 } 1015 LinkedList<PolyData> outerPoly = new LinkedList<PolyData>(); 1016 for (Way w : outerclosed) { 1017 outerPoly.add(new PolyData(w)); 1011 1018 } 1012 LinkedList<PolyData> poly = new LinkedList<PolyData>(); 1013 for (Way w : outerclosed) 1014 { 1015 poly.add(new PolyData(w)); 1016 } 1019 outerPoly.addAll(joinWays(outerjoin, incomplete ? null : r)); 1017 1020 for (Way wInner : innerclosed) 1018 1021 { 1019 Polygon polygon = new Polygon(); 1020 1021 for (Node n : wInner.getNodes()) 1022 { 1023 Point pInner = nc.getPoint(n); 1024 polygon.addPoint(pInner.x,pInner.y); 1025 } 1026 if(!wInner.isClosed()) 1027 { 1028 Point pInner = nc.getPoint(wInner.getNode(0)); 1029 polygon.addPoint(pInner.x,pInner.y); 1030 } 1031 PolyData o = null; 1032 for (PolyData pd : poly) 1033 { 1034 Integer c = pd.contains(polygon); 1035 if(c >= 1) 1036 { 1037 if(c > 1 && pd.way.isClosed()) 1038 { 1039 r.putError(tr("Intersection between ways ''{0}'' and ''{1}''.", 1040 pd.way.getDisplayName(DefaultNameFormatter.getInstance()), wInner.getDisplayName(DefaultNameFormatter.getInstance())), true); 1041 } 1042 if(o == null || o.contains(pd.poly) > 0) { 1043 o = pd; 1044 } 1045 } 1046 } 1047 if(o == null) 1048 { 1049 if(!incomplete) 1050 { 1051 r.putError(tr("Inner way ''{0}'' is outside.", 1052 wInner.getDisplayName(DefaultNameFormatter.getInstance())), true); 1053 } 1054 o = poly.get(0); 1055 } 1056 o.addInner(polygon); 1022 PolyData pdInner = new PolyData(wInner); 1023 // incomplete is probably redundant 1024 addInnerToOuters(r, incomplete, pdInner, outerPoly); 1057 1025 } 1026 for (PolyData pdInner : joinWays(innerjoin, incomplete ? null : r)) { 1027 addInnerToOuters(r, incomplete, pdInner, outerPoly); 1028 } 1058 1029 AreaElemStyle areaStyle = (AreaElemStyle)wayStyle; 1059 for (PolyData pd : poly) 1060 { 1030 for (PolyData pd : outerPoly) { 1061 1031 Polygon p = pd.get(); 1062 if( isPolygonVisible(p))1063 {1064 drawAreaPolygon(p, (data.isSelected(pd.way) || data.isSelected(r)) ? selectedColor 1065 : areaStyle.color);1066 visible = true;1067 }1032 if(!isPolygonVisible(p)) 1033 continue; 1034 1035 boolean selected = pd.selected || data.isSelected(pd.way) || data.isSelected(r); 1036 drawAreaPolygon(p, selected ? selectedColor : areaStyle.color); 1037 visible = true; 1068 1038 } 1069 1039 } 1070 1040 if(!visible) /* nothing visible, so disable relation and all its ways */ … … 1414 1384 } 1415 1385 } 1416 1386 1387 boolean drawable(OsmPrimitive osm) 1388 { 1389 return !osm.isDeleted() && !osm.isFiltered() && !osm.incomplete; 1390 } 1391 1417 1392 @Override 1418 1393 public void getColors() 1419 1394 { … … 1425 1400 1426 1401 DataSet data; 1427 1402 1403 <T extends OsmPrimitive> Collection<T> selectedLast(final DataSet data, Collection <T> prims) { 1404 ArrayList<T> sorted = new ArrayList<T>(prims); 1405 Collections.sort(sorted, 1406 new Comparator<T>() { 1407 public int compare(T o1, T o2) { 1408 boolean s1 = data.isSelected(o1); 1409 boolean s2 = data.isSelected(o2); 1410 if (s1 && !s2) 1411 return 1; 1412 if (!s1 && s2) 1413 return -1; 1414 return o1.compareTo(o2); 1415 } 1416 }); 1417 return sorted; 1418 } 1419 1428 1420 /* Shows areas before non-areas */ 1429 1421 @Override 1430 1422 public void visitAll(DataSet data, Boolean virtual) { … … 1433 1425 //profilerOmitDraw = Main.pref.getBoolean("mappaint.profiler.omitdraw",false); 1434 1426 1435 1427 useStyleCache = Main.pref.getBoolean("mappaint.cache",true); 1436 fillAreas = Main.pref.getInteger("mappaint.fillareas", 10000000);1428 int fillAreas = Main.pref.getInteger("mappaint.fillareas", 10000000); 1437 1429 fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref.getInteger("mappaint.fillalpha", 50)))); 1438 1430 showNames = Main.pref.getInteger("mappaint.shownames", 10000000); 1439 1431 showIcons = Main.pref.getInteger("mappaint.showicons", 10000000); … … 1468 1460 maxEN = nc.getEastNorth(nc.getWidth()-1,0); 1469 1461 1470 1462 1471 selectedCall = false;1472 1463 ++paintid; 1473 1464 viewid = nc.getViewID(); 1474 1465 … … 1491 1482 // profilerN = 0; 1492 1483 for (final Relation osm : data.relations) 1493 1484 { 1494 if( !osm.isDeleted() && !osm.isFiltered() && !osm.incomplete&& osm.mappaintVisibleCode != viewid)1485 if(drawable(osm) && osm.mappaintVisibleCode != viewid) 1495 1486 { 1496 osm.visit(this);1487 paintUnselectedRelation(osm); 1497 1488 // profilerN++; 1498 1489 } 1499 1490 } … … 1506 1497 1507 1498 /*** AREAS ***/ 1508 1499 // profilerN = 0; 1509 for (final Way osm : data.ways) 1510 { 1511 if (!osm.incomplete && !osm.isDeleted() && !osm.isFiltered() 1500 for (final Way osm : selectedLast(data, data.ways)) { 1501 if (drawable(osm) 1512 1502 && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid) 1513 1503 { 1514 1504 if(isPrimitiveArea(osm) && osm.mappaintDrawnAreaCode != paintid) 1515 1505 { 1516 osm.visit(this);1506 drawWay(osm, fillAreas); 1517 1507 // profilerN++; 1518 1508 } else { 1519 1509 noAreaWays.add(osm); … … 1530 1520 1531 1521 /*** WAYS ***/ 1532 1522 // profilerN = 0; 1533 fillAreas = 0; 1534 for (final OsmPrimitive osm : noAreaWays) 1523 for (final Way osm : noAreaWays) 1535 1524 { 1536 osm.visit(this);1525 drawWay(osm, 0); 1537 1526 // profilerN++; 1538 1527 } 1539 1528 … … 1548 1537 { 1549 1538 /*** WAYS (filling disabled) ***/ 1550 1539 // profilerN = 0; 1551 for (final OsmPrimitive osm: data.ways)1552 if ( !osm.incomplete && !osm.isDeleted() && !osm.isFiltered() && !data.isSelected(osm)1553 && osm.mappaintVisibleCode != viewid )1540 for (final Way way : data.ways) 1541 if (drawable(way) && !data.isSelected(way) 1542 && way.mappaintVisibleCode != viewid ) 1554 1543 { 1555 osm.visit(this);1544 drawWay(way, 0); 1556 1545 // profilerN++; 1557 1546 } 1558 1547 … … 1565 1554 } 1566 1555 1567 1556 /*** SELECTED ***/ 1568 selectedCall = true;1569 1557 //profilerN = 0; 1570 1558 for (final OsmPrimitive osm : data.getSelected()) { 1571 1559 if (!osm.incomplete && !osm.isDeleted() && !(osm instanceof Node) 1572 1560 && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid) 1573 1561 { 1574 osm.visit(this); 1562 osm.visit(new AbstractVisitor() { 1563 public void visit(Way w) { 1564 drawWay(w, 0); 1565 } 1566 public void visit(Node n) { 1567 drawNode(n); 1568 } 1569 public void visit(Relation r) { 1570 /* TODO: is it possible to do this like the nodes/ways code? */ 1571 //if(profilerOmitDraw) 1572 // return; 1573 r.mappaintVisibleCode = 0; 1574 for (RelationMember m : r.getMembers()) { 1575 if (m.isNode() && drawable(m.getMember())) { 1576 drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true); 1577 } 1578 } 1579 } 1580 }); 1575 1581 // profilerN++; 1576 1582 } 1577 1583 } … … 1587 1593 1588 1594 /*** NODES ***/ 1589 1595 //profilerN = 0; 1590 for (final OsmPrimitive osm : data.nodes)1596 for (final Node osm : data.nodes) 1591 1597 if (!osm.incomplete && !osm.isDeleted() && (data.isSelected(osm) || !osm.isFiltered()) 1592 1598 && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid) 1593 1599 { 1594 osm.visit(this);1600 drawNode(osm); 1595 1601 // profilerN++; 1596 1602 } 1597 1603
