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}