001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.imagery; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.text.MessageFormat; 007import java.util.ArrayList; 008import java.util.List; 009import java.util.Objects; 010 011import org.openstreetmap.gui.jmapviewer.Coordinate; 012import org.openstreetmap.josm.data.coor.LatLon; 013import org.openstreetmap.josm.data.osm.Node; 014import org.openstreetmap.josm.tools.CheckParameterUtil; 015import org.openstreetmap.josm.tools.Geometry; 016 017/** 018 * Data class to store the outline for background imagery coverage. 019 * 020 * Configuration data for imagery to describe the coverage area ({@link ImageryInfo.ImageryBounds}). 021 * @author Vincent 022 */ 023public class Shape { 024 025 private final List<Coordinate> coords = new ArrayList<>(); 026 027 public Shape(String asString, String separator) { 028 CheckParameterUtil.ensureParameterNotNull(asString, "asString"); 029 String[] components = asString.split(separator); 030 if (components.length % 2 != 0) 031 throw new IllegalArgumentException(MessageFormat.format("Even number of doubles expected in string, got {0}: {1}", 032 components.length, asString)); 033 for (int i = 0; i < components.length; i += 2) { 034 addPoint(components[i], components[i+1]); 035 } 036 } 037 038 /** 039 * Constructs a new empty {@code Shape}. 040 */ 041 public Shape() { 042 // shape contents can be set later with addPoint() 043 } 044 045 public String encodeAsString(String separator) { 046 StringBuilder sb = new StringBuilder(); 047 for (Coordinate c : coords) { 048 if (sb.length() != 0) { 049 sb.append(separator); 050 } 051 sb.append(c.getLat()).append(separator).append(c.getLon()); 052 } 053 return sb.toString(); 054 } 055 056 public List<Coordinate> getPoints() { 057 return coords; 058 } 059 060 public boolean contains(LatLon latlon) { 061 if (latlon == null) 062 return false; 063 List<Node> nodes = new ArrayList<>(coords.size()); 064 for (Coordinate c : coords) { 065 nodes.add(new Node(new LatLon(c.getLat(), c.getLon()))); 066 } 067 return Geometry.nodeInsidePolygon(new Node(latlon), nodes); 068 } 069 070 public void addPoint(String sLat, String sLon) { 071 CheckParameterUtil.ensureParameterNotNull(sLat, "sLat"); 072 CheckParameterUtil.ensureParameterNotNull(sLon, "sLon"); 073 074 double lat, lon; 075 076 try { 077 lat = Double.parseDouble(sLat); 078 if (!LatLon.isValidLat(lat)) 079 throw new IllegalArgumentException(tr("Illegal latitude value ''{0}''", lat)); 080 } catch (NumberFormatException e) { 081 throw new IllegalArgumentException(MessageFormat.format("Illegal double value ''{0}''", sLat), e); 082 } 083 084 try { 085 lon = Double.parseDouble(sLon); 086 if (!LatLon.isValidLon(lon)) 087 throw new IllegalArgumentException(tr("Illegal longitude value ''{0}''", lon)); 088 } catch (NumberFormatException e) { 089 throw new IllegalArgumentException(MessageFormat.format("Illegal double value ''{0}''", sLon), e); 090 } 091 092 coords.add(new Coordinate(LatLon.roundToOsmPrecision(lat), LatLon.roundToOsmPrecision(lon))); 093 } 094 095 @Override 096 public int hashCode() { 097 return Objects.hash(coords); 098 } 099 100 @Override 101 public boolean equals(Object obj) { 102 if (this == obj) return true; 103 if (obj == null || getClass() != obj.getClass()) return false; 104 Shape shape = (Shape) obj; 105 return Objects.equals(coords, shape.coords); 106 } 107}