package geography; import java.awt.geom.Rectangle2D; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import gui.CartographyDocument; /** * A class for reading geographic shapes from an input stream and creating a CartographyDocument * containing those shapes. */ public class GeographicShapesReader { private BufferedReader in; private MapProjection proj; /** * @param is * The input stream to read the shapes from * @param proj * The map projection to use when converting geographic coordinates to Cartesian * coordinates */ public GeographicShapesReader(final InputStream is, final MapProjection proj) { this.in = new BufferedReader(new InputStreamReader(is)); this.proj = proj; } /** * @return A CartographyDocument containing the shapes read from the input stream. */ public CartographyDocument read() { double maxX = Double.NEGATIVE_INFINITY; double maxY = Double.NEGATIVE_INFINITY; double minX = Double.POSITIVE_INFINITY; double minY = Double.POSITIVE_INFINITY; Map shapes = new HashMap<>(); String currentLine; try { while ((currentLine = in.readLine()) != null) { Map parsed = new LinkedHashMap<>(); String[] tokens = currentLine.trim().split("(?=Type:|ID:|Code:)"); for (String token : tokens) { if (token.isBlank()) continue; int colonIdx = token.indexOf(':'); String key = token.substring(0, colonIdx).trim(); String value = token.substring(colonIdx + 1).trim(); parsed.put(key, value); } String type = parsed.get("Type"); String id = parsed.get("ID"); PiecewiseLinearCurve shape; switch (type) { case "PiecewiseLinearCurve": shape = new PiecewiseLinearCurve(id); break; case "Polygon": shape = new Polygon(id); break; case "Comment": in.readLine(); // skip the END continue; default: return null; } while ((currentLine = in.readLine()) != null) { currentLine = currentLine.trim(); if (currentLine.equals("END")) { break; } String[] strCoords = currentLine.trim().split("\\s+"); double[] coords = new double[] {Double.parseDouble(strCoords[0]), Double.parseDouble(strCoords[1])}; double[] projCoords = proj.forward(coords); shape.add(projCoords); maxX = Math.max(maxX, projCoords[0]); maxY = Math.max(maxY, projCoords[1]); minX = Math.min(minX, projCoords[0]); minY = Math.min(minY, projCoords[1]); } shapes.put(id, shape); } } catch (IOException e) { e.printStackTrace(); } Rectangle2D.Double bounds = new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY); return new CartographyDocument<>(shapes, bounds); } }