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 * @author Vincent 019 * 020 */ 021public class Shape { 022 023 private final List<Coordinate> coords = new ArrayList<>(); 024 025 public Shape(String asString, String separator) { 026 CheckParameterUtil.ensureParameterNotNull(asString, "asString"); 027 String[] components = asString.split(separator); 028 if (components.length % 2 != 0) 029 throw new IllegalArgumentException(MessageFormat.format("Even number of doubles expected in string, got {0}: {1}", 030 components.length, asString)); 031 for (int i = 0; i < components.length; i += 2) { 032 addPoint(components[i], components[i+1]); 033 } 034 } 035 036 /** 037 * Constructs a new empty {@code Shape}. 038 */ 039 public Shape() { 040 // shape contents can be set later with addPoint() 041 } 042 043 public String encodeAsString(String separator) { 044 StringBuilder sb = new StringBuilder(); 045 for (Coordinate c : coords) { 046 if (sb.length() != 0) { 047 sb.append(separator); 048 } 049 sb.append(c.getLat()).append(separator).append(c.getLon()); 050 } 051 return sb.toString(); 052 } 053 054 public List<Coordinate> getPoints() { 055 return coords; 056 } 057 058 public boolean contains(LatLon latlon) { 059 if (latlon == null) 060 return false; 061 List<Node> nodes = new ArrayList<>(coords.size()); 062 for (Coordinate c : coords) { 063 nodes.add(new Node(new LatLon(c.getLat(), c.getLon()))); 064 } 065 return Geometry.nodeInsidePolygon(new Node(latlon), nodes); 066 } 067 068 public void addPoint(String sLat, String sLon) { 069 CheckParameterUtil.ensureParameterNotNull(sLat, "sLat"); 070 CheckParameterUtil.ensureParameterNotNull(sLon, "sLon"); 071 072 double lat, lon; 073 074 try { 075 lat = Double.parseDouble(sLat); 076 if (!LatLon.isValidLat(lat)) 077 throw new IllegalArgumentException(tr("Illegal latitude value ''{0}''", lat)); 078 } catch (NumberFormatException e) { 079 throw new IllegalArgumentException(MessageFormat.format("Illegal double value ''{0}''", sLat), e); 080 } 081 082 try { 083 lon = Double.parseDouble(sLon); 084 if (!LatLon.isValidLon(lon)) 085 throw new IllegalArgumentException(tr("Illegal longitude value ''{0}''", lon)); 086 } catch (NumberFormatException e) { 087 throw new IllegalArgumentException(MessageFormat.format("Illegal double value ''{0}''", sLon), e); 088 } 089 090 coords.add(new Coordinate(LatLon.roundToOsmPrecision(lat), LatLon.roundToOsmPrecision(lon))); 091 } 092 093 @Override 094 public int hashCode() { 095 return Objects.hash(coords); 096 } 097 098 @Override 099 public boolean equals(Object obj) { 100 if (this == obj) return true; 101 if (obj == null || getClass() != obj.getClass()) return false; 102 Shape shape = (Shape) obj; 103 return Objects.equals(coords, shape.coords); 104 } 105}