Changeset 10817 in josm
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/MultipolygonBuilder.java
r10632 r10817 14 14 import java.util.HashSet; 15 15 import java.util.List; 16 import java.util.Map; 16 17 import java.util.Set; 17 18 import java.util.concurrent.ForkJoinPool; 18 19 import java.util.concurrent.ForkJoinTask; 19 20 import java.util.concurrent.RecursiveTask; 21 import java.util.stream.Collectors; 20 22 21 23 import org.openstreetmap.josm.Main; 24 import org.openstreetmap.josm.tools.CheckParameterUtil; 22 25 import org.openstreetmap.josm.tools.Geometry; 23 26 import org.openstreetmap.josm.tools.Geometry.PolygonIntersection; … … 165 168 166 169 /** 170 * Joins the given {@code multipolygon} to a pair of outer and inner multipolygon rings. 171 * 172 * @param multipolygon the multipolygon to join. 173 * @return a pair of outer and inner multipolygon rings. 174 * @throws JoinedPolygonCreationException if the creation fails. 175 */ 176 public static Pair<List<JoinedPolygon>, List<JoinedPolygon>> joinWays(Relation multipolygon) throws JoinedPolygonCreationException { 177 CheckParameterUtil.ensureThat(multipolygon.isMultipolygon(), "multipolygon.isMultipolygon"); 178 final Map<String, Set<Way>> members = multipolygon.getMembers().stream() 179 .filter(RelationMember::isWay) 180 .collect(Collectors.groupingBy(RelationMember::getRole, Collectors.mapping(RelationMember::getWay, Collectors.toSet()))); 181 final List<JoinedPolygon> outerRings = joinWays(members.getOrDefault("outer", Collections.emptySet())); 182 final List<JoinedPolygon> innerRings = joinWays(members.getOrDefault("inner", Collections.emptySet())); 183 return Pair.create(outerRings, innerRings); 184 } 185 186 /** 167 187 * Joins the given {@code ways} to multipolygon rings. 168 188 * @param ways the ways to join. -
trunk/src/org/openstreetmap/josm/io/GeoJSONWriter.java
r10173 r10817 7 7 import java.util.HashMap; 8 8 import java.util.Iterator; 9 import java.util.List; 9 10 import java.util.Map; 10 11 import java.util.Map.Entry; 12 import java.util.stream.Stream; 11 13 12 14 import javax.json.Json; … … 20 22 import org.openstreetmap.josm.data.coor.LatLon; 21 23 import org.openstreetmap.josm.data.osm.DataSet; 22 import org.openstreetmap.josm.data.osm.INode; 23 import org.openstreetmap.josm.data.osm.IRelation; 24 import org.openstreetmap.josm.data.osm.IWay; 24 import org.openstreetmap.josm.data.osm.MultipolygonBuilder; 25 import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygon; 25 26 import org.openstreetmap.josm.data.osm.Node; 26 27 import org.openstreetmap.josm.data.osm.OsmPrimitive; 28 import org.openstreetmap.josm.data.osm.Relation; 27 29 import org.openstreetmap.josm.data.osm.Way; 28 import org.openstreetmap.josm.data.osm.visitor. PrimitiveVisitor;30 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor; 29 31 import org.openstreetmap.josm.data.projection.Projection; 30 32 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 33 import org.openstreetmap.josm.gui.mappaint.ElemStyles; 34 import org.openstreetmap.josm.tools.Pair; 31 35 32 36 /** … … 80 84 } 81 85 82 private class GeometryPrimitiveVisitor implements PrimitiveVisitor {86 private class GeometryPrimitiveVisitor extends AbstractVisitor { 83 87 84 88 private final JsonObjectBuilder geomObj; … … 89 93 90 94 @Override 91 public void visit( INode n) {95 public void visit(Node n) { 92 96 geomObj.add("type", "Point"); 93 97 LatLon ll = n.getCoor(); 94 98 if (ll != null) { 95 geomObj.add("coordinates", getCoorArray( Json.createArrayBuilder(), n.getCoor()));99 geomObj.add("coordinates", getCoorArray(null, n.getCoor())); 96 100 } 97 101 } 98 102 99 103 @Override 100 public void visit(IWay w) { 101 geomObj.add("type", "LineString"); 102 if (w instanceof Way) { 103 JsonArrayBuilder array = Json.createArrayBuilder(); 104 for (Node n : ((Way) w).getNodes()) { 105 LatLon ll = n.getCoor(); 106 if (ll != null) { 107 array.add(getCoorArray(Json.createArrayBuilder(), ll)); 108 } 104 public void visit(Way w) { 105 if (w != null) { 106 final JsonArrayBuilder array = getCoorsArray(w.getNodes()); 107 if (ElemStyles.hasAreaElemStyle(w, false)) { 108 final JsonArrayBuilder container = Json.createArrayBuilder().add(array); 109 geomObj.add("type", "Polygon"); 110 geomObj.add("coordinates", container); 111 } else { 112 geomObj.add("type", "LineString"); 113 geomObj.add("coordinates", array); 109 114 } 110 geomObj.add("coordinates", array);111 115 } 112 116 } 113 117 114 118 @Override 115 public void visit(IRelation r) { 116 // Do nothing 119 public void visit(Relation r) { 120 if (r != null && r.isMultipolygon() && !r.hasIncompleteMembers()) { 121 final Pair<List<JoinedPolygon>, List<JoinedPolygon>> mp = MultipolygonBuilder.joinWays(r); 122 final JsonArrayBuilder polygon = Json.createArrayBuilder(); 123 Stream.concat(mp.a.stream(), mp.b.stream()) 124 .map(p -> getCoorsArray(p.getNodes()) 125 // since first node is not duplicated as last node 126 .add(getCoorArray(null, p.getNodes().get(0).getCoor()))) 127 .forEach(polygon::add); 128 geomObj.add("type", "MultiPolygon"); 129 final JsonArrayBuilder multiPolygon = Json.createArrayBuilder().add(polygon); 130 geomObj.add("coordinates", multiPolygon); 131 } 117 132 } 118 133 } … … 123 138 124 139 private static JsonArrayBuilder getCoorArray(JsonArrayBuilder builder, EastNorth c) { 125 return builder 140 return builder != null ? builder : Json.createArrayBuilder() 126 141 .add(BigDecimal.valueOf(c.getX()).setScale(11, RoundingMode.HALF_UP)) 127 142 .add(BigDecimal.valueOf(c.getY()).setScale(11, RoundingMode.HALF_UP)); 143 } 144 145 private JsonArrayBuilder getCoorsArray(Iterable<Node> nodes) { 146 final JsonArrayBuilder builder = Json.createArrayBuilder(); 147 for (Node n : nodes) { 148 LatLon ll = n.getCoor(); 149 if (ll != null) { 150 builder.add(getCoorArray(null, ll)); 151 } 152 } 153 return builder; 128 154 } 129 155 … … 177 203 JsonArrayBuilder array = Json.createArrayBuilder(); 178 204 if (ds != null) { 179 for (Node n : ds.getNodes()) { 180 appendPrimitive(n, array); 181 } 182 for (Way w : ds.getWays()) { 183 appendPrimitive(w, array); 184 } 205 ds.allPrimitives().forEach(p -> appendPrimitive(p, array)); 185 206 } 186 207 object.add("features", array); -
trunk/src/org/openstreetmap/josm/tools/Geometry.java
r10797 r10817 12 12 import java.util.Comparator; 13 13 import java.util.EnumSet; 14 import java.util.HashSet;15 14 import java.util.LinkedHashSet; 16 15 import java.util.List; … … 26 25 import org.openstreetmap.josm.data.osm.BBox; 27 26 import org.openstreetmap.josm.data.osm.MultipolygonBuilder; 27 import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygon; 28 28 import org.openstreetmap.josm.data.osm.Node; 29 29 import org.openstreetmap.josm.data.osm.NodePositionComparator; 30 30 import org.openstreetmap.josm.data.osm.OsmPrimitive; 31 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;32 31 import org.openstreetmap.josm.data.osm.Relation; 33 import org.openstreetmap.josm.data.osm.RelationMember;34 32 import org.openstreetmap.josm.data.osm.Way; 35 33 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon; … … 863 861 } 864 862 865 public static class MultiPolygonMembers {866 public final Set<Way> outers = new HashSet<>();867 public final Set<Way> inners = new HashSet<>();868 869 public MultiPolygonMembers(Relation multiPolygon) {870 for (RelationMember m : multiPolygon.getMembers()) {871 if (m.getType().equals(OsmPrimitiveType.WAY)) {872 if ("outer".equals(m.getRole())) {873 outers.add(m.getWay());874 } else if ("inner".equals(m.getRole())) {875 inners.add(m.getWay());876 }877 }878 }879 }880 }881 882 863 /** 883 864 * Tests if the {@code node} is inside the multipolygon {@code multiPolygon}. The nullable argument … … 904 885 public static boolean isPolygonInsideMultiPolygon(List<Node> nodes, Relation multiPolygon, Predicate<Way> isOuterWayAMatch) { 905 886 // Extract outer/inner members from multipolygon 906 final MultiPolygonMembers mpm = new MultiPolygonMembers(multiPolygon); 907 // Construct complete rings for the inner/outer members 908 final List<MultipolygonBuilder.JoinedPolygon> outerRings; 909 final List<MultipolygonBuilder.JoinedPolygon> innerRings; 887 final Pair<List<JoinedPolygon>, List<JoinedPolygon>> outerInner; 910 888 try { 911 outerRings = MultipolygonBuilder.joinWays(mpm.outers); 912 innerRings = MultipolygonBuilder.joinWays(mpm.inners); 889 outerInner = MultipolygonBuilder.joinWays(multiPolygon); 913 890 } catch (MultipolygonBuilder.JoinedPolygonCreationException ex) { 914 891 Main.trace(ex); … … 917 894 } 918 895 // Test if object is inside an outer member 919 for ( MultipolygonBuilder.JoinedPolygon out : outerRings) {896 for (JoinedPolygon out : outerInner.a) { 920 897 if (nodes.size() == 1 921 898 ? nodeInsidePolygon(nodes.get(0), out.getNodes()) … … 924 901 boolean insideInner = false; 925 902 // If inside an outer, check it is not inside an inner 926 for ( MultipolygonBuilder.JoinedPolygon in : innerRings) {903 for (JoinedPolygon in : outerInner.b) { 927 904 if (polygonIntersection(in.getNodes(), out.getNodes()) == PolygonIntersection.FIRST_INSIDE_SECOND 928 905 && (nodes.size() == 1 -
trunk/test/unit/org/openstreetmap/josm/io/GeoJSONWriterTest.java
r10171 r10817 3 3 4 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertTrue; 5 6 6 7 import org.junit.BeforeClass; 7 8 import org.junit.Test; 8 9 import org.openstreetmap.josm.JOSMFixture; 10 import org.openstreetmap.josm.TestUtils; 9 11 import org.openstreetmap.josm.data.coor.LatLon; 10 12 import org.openstreetmap.josm.data.osm.DataSet; … … 12 14 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 13 15 import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference; 16 17 import java.io.FileInputStream; 14 18 15 19 /** … … 66 70 "}").replace("'", "\""), writer.write().trim()); 67 71 } 72 73 /** 74 * Unit test for multipolygon 75 */ 76 @Test 77 public void testMultipolygon() throws Exception { 78 try (FileInputStream in = new FileInputStream(TestUtils.getTestDataRoot() + "multipolygon.osm")) { 79 DataSet ds = OsmReader.parseDataSet(in, null); 80 final OsmDataLayer layer = new OsmDataLayer(ds, "foo", null); 81 final GeoJSONWriter writer = new GeoJSONWriter(layer, ProjectionPreference.wgs84.getProjection()); 82 assertTrue(writer.write().contains("MultiPolygon")); 83 } 84 } 68 85 }
Note:
See TracChangeset
for help on using the changeset viewer.