Changeset 34860 in osm for applications/editors/josm/plugins/poly
- Timestamp:
- 2019-01-25T06:45:38+01:00 (6 years ago)
- Location:
- applications/editors/josm/plugins/poly
- Files:
-
- 13 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/poly
- Property svn:ignore
-
old new 1 bin 1 2 build 2 b in3 buildtest 3 4 checkstyle-josm-poly.xml 4 5 findbugs-josm-poly.xml 5 6 javadoc 7 spotbugs-josm-poly.xml
-
- Property svn:ignore
-
applications/editors/josm/plugins/poly/.classpath
r32680 r34860 2 2 <classpath> 3 3 <classpathentry kind="src" path="src"/> 4 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> 4 <classpathentry kind="src" output="buildtest" path="test/unit"> 5 <attributes> 6 <attribute name="test" value="true"/> 7 </attributes> 8 </classpathentry> 9 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 5 10 <classpathentry combineaccessrules="false" kind="src" path="/JOSM"/> 6 <classpathentry kind="output" path="bin"/> 11 <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/> 12 <classpathentry kind="output" path="build"/> 7 13 </classpath> -
applications/editors/josm/plugins/poly/.project
r33003 r34860 4 4 <comment></comment> 5 5 <projects> 6 <project>josm</project> 6 7 </projects> 7 8 <buildSpec> -
applications/editors/josm/plugins/poly/src/poly/PolyExporter.java
r34098 r34860 2 2 package poly; 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.io.BufferedWriter; 5 7 import java.io.File; 6 import java.io.FileOutputStream;7 8 import java.io.IOException; 8 import java.io.OutputStreamWriter; 9 import java.util.ArrayList; 10 import java.util.LinkedHashMap; 11 import java.util.List; 9 import java.nio.charset.StandardCharsets; 10 import java.nio.file.Files; 11 import java.util.HashSet; 12 12 import java.util.Locale; 13 import java.util.Map; 14 import java.util.TreeMap; 13 import java.util.Set; 15 14 16 15 import org.openstreetmap.josm.data.osm.DataSet; 17 16 import org.openstreetmap.josm.data.osm.Node; 18 import org.openstreetmap.josm.data.osm.OsmPrimitive;19 17 import org.openstreetmap.josm.data.osm.Relation; 20 18 import org.openstreetmap.josm.data.osm.RelationMember; … … 28 26 * 29 27 * @author zverik 28 * @author Gerd Petermann 30 29 */ 31 30 public class PolyExporter extends OsmExporter { 32 31 32 /** 33 * Create exporter. 34 */ 33 35 public PolyExporter() { 34 36 super(PolyType.FILE_FILTER); … … 38 40 public void exportData(File file, Layer layer) throws IOException { 39 41 if (layer instanceof OsmDataLayer) { 40 try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF8"))) { 42 if (((OsmDataLayer) layer).getDataSet().getWays().stream().anyMatch(w -> !w.isClosed())) { 43 throw new IOException(tr("Data contains unclosed ways.")); 44 } 45 try (BufferedWriter writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) { 41 46 DataSet ds = ((OsmDataLayer) layer).getDataSet(); 42 Map<Way, Boolean> ways = new TreeMap<>(); 43 String polygonName = file.getName(); 44 if (polygonName.indexOf('.') > 0) 45 polygonName = polygonName.substring(0, polygonName.indexOf('.')); 46 for (Way w : ds.getWays()) { 47 if (w.isClosed()) { 48 boolean outer = isOuter(w); 49 ways.put(w, outer); 50 if (w.hasKey("name")) 51 polygonName = w.get("name").replace("\n", " "); 47 HashSet<Way> written = new HashSet<>(); 48 boolean firstFile = true; 49 String fileName = file.getName(); 50 if (fileName.lastIndexOf('.') > 0) { 51 // remove extension 52 fileName = fileName.substring(0, fileName.lastIndexOf('.')); 53 } 54 55 for (Relation rel : ds.getRelations()) { 56 if (rel.isMultipolygon()) { 57 if (!firstFile) { 58 writer.newLine(); 59 } 60 writeRelation(writer, fileName, rel, written); 61 firstFile = false; 52 62 } 53 63 } 54 ways = sortOuterInner(ways); 55 64 65 if (firstFile) { 66 writer.write(fileName); 67 } 56 68 int counter = 1; 57 writer.write(polygonName); 58 writer.newLine(); 59 for (Way w : ways.keySet()) { 60 if (!ways.get(w)) 61 writer.write('!'); 62 writer.write(String.valueOf(counter++)); 63 writer.newLine(); 64 for (Node n : w.getNodes()) { 65 writer.write(String.format(Locale.ENGLISH, " %f %f", n.getCoor().lon(), n.getCoor().lat())); 66 writer.newLine(); 69 for (Way w : ds.getWays()) { 70 if (!written.contains(w)) { 71 writeWay(writer, w, counter); 67 72 } 68 writer.write("END");69 writer.newLine();70 73 } 71 74 writer.write("END"); … … 75 78 } 76 79 77 private boolean isOuter(Way w) { 78 for (OsmPrimitive p : w.getReferrers()) { 79 if (p instanceof Relation && ((Relation) p).isMultipolygon()) { 80 for (RelationMember m : ((Relation) p).getMembers()) { 81 if (m.refersTo(w) && "inner".equals(m.getRole())) { 82 return false; 83 } 84 } 80 private static void writeRelation(BufferedWriter writer, String fileName, Relation rel, Set<Way> written) throws IOException { 81 String polygonName = fileName; 82 if (rel.getName() != null) 83 polygonName = rel.getName(); 84 writer.write(polygonName); 85 writer.newLine(); 86 int counter = 1; 87 for (RelationMember rm: rel.getMembers()) { 88 if (rm.isWay()) { 89 if ("inner".equals(rm.getRole())) 90 writer.write('!'); 91 Way w = rm.getWay(); 92 counter = writeWay(writer, w, counter); 93 written.add(w); 85 94 } 86 95 } 87 return true;88 96 } 89 97 90 private Map<Way, Boolean> sortOuterInner(Map<Way, Boolean> ways) { 91 LinkedHashMap<Way, Boolean> result = new LinkedHashMap<>(ways.size()); 92 List<Way> inner = new ArrayList<>(); 93 for (Way w : ways.keySet()) { 94 Boolean outer = ways.get(w); 95 if (outer) 96 result.put(w, outer); 97 else 98 inner.add(w); 98 private static int writeWay(BufferedWriter writer, Way w, int counter) throws IOException { 99 String name = w.getName(); 100 if (name == null) { 101 name = String.valueOf(counter++); 102 } 103 writer.write(name); 104 writer.newLine(); 105 106 for (Node n : w.getNodes()) { 107 writer.write(String.format(Locale.ENGLISH, " %f %f", n.getCoor().lon(), n.getCoor().lat())); 108 writer.newLine(); 99 109 } 100 for (Way w : inner) { 101 result.put(w, Boolean.FALSE); 102 } 103 return result; 110 writer.write("END"); 111 writer.newLine(); 112 return counter; 104 113 } 105 114 } -
applications/editors/josm/plugins/poly/src/poly/PolyImporter.java
r34546 r34860 8 8 import java.io.InputStream; 9 9 import java.io.InputStreamReader; 10 import java.nio.charset.StandardCharsets; 10 11 import java.util.ArrayList; 11 12 import java.util.List; … … 27 28 import org.openstreetmap.josm.io.IllegalDataException; 28 29 import org.openstreetmap.josm.tools.CheckParameterUtil; 29 import org.xml.sax.SAXException;30 30 31 31 /** … … 33 33 * 34 34 * @author zverik 35 * @author Gerd Petermann 35 36 */ 36 37 public class PolyImporter extends OsmImporter { 38 /** 39 * Create importer. 40 */ 37 41 public PolyImporter() { 38 42 super(PolyType.FILE_FILTER); 39 43 } 40 44 41 protected DataSet parseDataSet(final String source) throws IOException, SAXException, IllegalDataException { 42 return parseDataSet(new CachedFile(source).getInputStream(), NullProgressMonitor.INSTANCE); 45 protected DataSet parseDataSet(final String source) throws IOException, IllegalDataException { 46 try (CachedFile cf = new CachedFile(source)) { 47 return parseDataSet(cf.getInputStream(), NullProgressMonitor.INSTANCE); 48 } 43 49 } 44 50 … … 49 55 CheckParameterUtil.ensureParameterNotNull(in, "in"); 50 56 51 try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF8"))) {52 progressMonitor.beginTask(tr("Reading polygon filter file..."), 2);57 try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { 58 progressMonitor.beginTask(tr("Reading polygon filter file..."), 3); 53 59 progressMonitor.indeterminateSubTask(tr("Reading polygon filter file...")); 54 60 List<Area> areas = loadPolygon(reader); … … 66 72 } 67 73 68 private List<Area> loadPolygon(BufferedReader reader) throws IllegalDataException, IOException { 74 private static List<Area> loadPolygon(BufferedReader reader) throws IllegalDataException, IOException { 69 75 String name = reader.readLine(); 70 76 if (name == null || name.trim().length() == 0) … … 76 82 while (true) { 77 83 String line; 78 do { 79 line = reader.readLine(); 80 if (line == null) 81 throw new IllegalDataException("File ended prematurely without END record"); 82 line = line.trim(); 83 } while (line.length() == 0); 84 85 if (line.equals("END")) { 86 if (!parsingSection) 87 break; 88 else { 84 line = reader.readLine(); 85 if (line == null) 86 break; 87 line = line.trim(); 88 if (line.isEmpty()) { 89 // empty line is only allowed after a complete file (one or more rings belonging to one polygon) 90 if (parsingSection) 91 throw new IllegalDataException(tr("Empty line in coordinate section")); 92 area = null; 93 parsingSection = false; 94 name = null; 95 } else if (line.equals("END")) { 96 if (!parsingSection) { 97 area = null; 98 } else { 89 99 // an area has been read 90 100 if (area.getNodeCount() < 2) 91 101 throw new IllegalDataException(tr("There are less than 2 points in an area")); 92 102 areas.add(area); 93 if (areas.size() == 1) 94 areas.get(0).setPolygonName(name); 103 area.setPolygonName(name); 95 104 parsingSection = false; 96 105 } 97 } else { 106 } else if (name == null) { 107 name = line; 108 } else if (line.length() > 0) { 98 109 if (!parsingSection) { 110 if (line.indexOf(' ') >= 0) { 111 boolean coordInsteadOfName = false; 112 try { 113 LatLon ll = parseCoordinate(line); 114 if (ll.isValid()) { 115 coordInsteadOfName = true; 116 } 117 } catch (IllegalDataException e) { 118 coordInsteadOfName = false; 119 } 120 if (coordInsteadOfName) { 121 throw new IllegalDataException(tr("Found coordinates ''{0}'' instead of name", line)); 122 } 123 } 99 124 area = new Area(line); 100 125 parsingSection = true; 101 126 } else { 102 // reading area, parse coordinates 103 String[] tokens = line.split("\\s+"); 104 double[] coords = new double[2]; 105 int tokenCount = 0; 106 for (String token : tokens) { 107 if (token.length() > 0) { 108 if (tokenCount > 2) 109 throw new IllegalDataException(tr("A polygon coordinate line must contain exactly 2 numbers")); 110 try { 111 coords[tokenCount++] = Double.parseDouble(token); 112 } catch (NumberFormatException e) { 113 throw new IllegalDataException(tr("Unable to parse {0} as a number", token)); 114 } 115 } 116 } 117 if (tokenCount < 2) 118 throw new IllegalDataException(tr("A polygon coordinate line must contain exactly 2 numbers")); 119 LatLon coord = new LatLon(coords[1], coords[0]); 127 LatLon coord = parseCoordinate(line); 120 128 if (!coord.isValid()) { 121 129 // fix small deviations … … 126 134 if (lat < -90.0 && lat > -95.0) lat = -90.0; 127 135 if (lat > 90.0 && lat < 95.0) lat = 90.0; 136 coord = new LatLon(lat, lon); 128 137 fixedCoords++; 129 coord = new LatLon(lat, lon);130 138 if (!coord.isValid()) 131 139 throw new IllegalDataException(tr("Invalid coordinates were found: {0}, {1}", coord.lat(), coord.lon())); 132 140 } 133 area.addNode( coord);141 area.addNode(parseCoordinate(line)); 134 142 } 135 143 } … … 141 149 } 142 150 143 private DataSet constructDataSet(List<Area> areas) { 151 /** 152 * Parse a line that should contain two double values which describe a latitude/longitude pair. 153 * @param line the line to parse 154 * @return a new LatLon 155 * @throws IllegalDataException in case of error 156 */ 157 private static LatLon parseCoordinate(String line) throws IllegalDataException { 158 String[] tokens = line.split("\\s+"); 159 double[] coords = new double[2]; 160 int tokenCount = 0; 161 for (String token : tokens) { 162 if (token.length() > 0) { 163 if (tokenCount > 2) 164 break; 165 try { 166 coords[tokenCount++] = Double.parseDouble(token); 167 } catch (NumberFormatException e) { 168 throw new IllegalDataException(tr("Unable to parse {0} as a number", token)); 169 } 170 } 171 } 172 if (tokenCount != 2) 173 throw new IllegalDataException(tr("A polygon coordinate line must contain exactly 2 numbers")); 174 return new LatLon(coords[1], coords[0]); 175 } 176 177 private static DataSet constructDataSet(List<Area> areas) { 144 178 DataSet ds = new DataSet(); 145 179 ds.setUploadPolicy(UploadPolicy.DISCOURAGED); 146 180 147 boolean foundInner = false; 181 182 List<Area> curretSet = new ArrayList<>(); 183 148 184 for (Area area : areas) { 149 if (!area.isOuter()) 150 foundInner = true; 151 area.constructWay(ds); 152 } 153 154 if (foundInner) { 185 if (!curretSet.isEmpty() && !area.polygonName.equals(curretSet.get(0).polygonName)) { 186 constructPrimitive(ds, curretSet); 187 curretSet.clear(); 188 } 189 curretSet.add(area); 190 } 191 if (!curretSet.isEmpty()) 192 constructPrimitive(ds, curretSet); 193 194 return ds; 195 } 196 197 private static void constructPrimitive(DataSet ds, List<Area> areas) { 198 boolean isMultipolygon = areas.size() > 1; 199 for (Area area : areas) { 200 area.constructWay(ds, isMultipolygon); 201 } 202 203 if (isMultipolygon) { 155 204 Relation mp = new Relation(); 156 205 mp.put("type", "multipolygon"); 206 Area outer = areas.get(0); 207 if (outer.polygonName != null) { 208 mp.put("name", outer.polygonName); 209 } 157 210 for (Area area : areas) { 158 211 mp.addMember(new RelationMember(area.isOuter() ? "outer" : "inner", area.getWay())); … … 160 213 ds.addPrimitive(mp); 161 214 } 162 163 return ds;164 215 } 165 216 … … 178 229 nodes = new ArrayList<>(); 179 230 way = null; 180 polygonName = null;231 polygonName = ""; 181 232 } 182 233 183 234 public void setPolygonName(String polygonName) { 184 this.polygonName = polygonName; 235 if (polygonName != null) { 236 this.polygonName = polygonName; 237 } 185 238 } 186 239 … … 202 255 } 203 256 204 public void constructWay(DataSet ds) { 257 public void constructWay(DataSet ds, boolean isMultipolygon) { 205 258 way = new Way(); 206 259 for (LatLon coord : nodes) { … … 210 263 } 211 264 way.addNode(way.getNode(0)); 212 if (polygonName != null) 213 way.put("name", polygonName); 265 if (isMultipolygon && name != null) 266 way.put("name", name); 267 else { 268 if (polygonName != null) 269 way.put("name", polygonName); 270 } 214 271 ds.addPrimitive(way); 215 272 } -
applications/editors/josm/plugins/poly/src/poly/PolyType.java
r34546 r34860 10 10 * 11 11 * @author zverik 12 * @author Gerd Petermann 12 13 */ 13 public interface PolyType { 14 String EXTENSION = "poly"; 15 ExtensionFileFilter FILE_FILTER = new ExtensionFileFilter( 14 15 final class PolyType { 16 private static final String EXTENSION = "poly"; 17 18 /** filter for osmosis poly files */ 19 static final ExtensionFileFilter FILE_FILTER = new ExtensionFileFilter( 16 20 EXTENSION, EXTENSION, tr("Osmosis polygon filter files") + " (*." + EXTENSION + ")"); 21 private PolyType() {} 17 22 }
Note:
See TracChangeset
for help on using the changeset viewer.