001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.tools;
003
004import java.awt.geom.Area;
005import java.awt.geom.Path2D;
006import java.util.Collection;
007
008import org.openstreetmap.josm.data.coor.LatLon;
009import org.openstreetmap.josm.data.osm.BBox;
010import org.openstreetmap.josm.data.osm.Relation;
011import org.openstreetmap.josm.data.osm.Way;
012
013/**
014 * Implementation of simple boolean {@link GeoProperty}.
015 */
016public class DefaultGeoProperty implements GeoProperty<Boolean> {
017
018    private final Area area;
019
020    /**
021     * Create DefaultGeoProperty based on a collection of closed ways.
022     *
023     * @param ways the ways forming the area
024     */
025    public DefaultGeoProperty(Collection<Way> ways) {
026        Path2D path = new Path2D.Double();
027        path.setWindingRule(Path2D.WIND_EVEN_ODD);
028        for (Way w : ways) {
029            Geometry.buildPath2DLatLon(w.getNodes(), path);
030        }
031        this.area = new Area(path);
032    }
033
034    /**
035     * Create DefaultGeoProperty based on a multipolygon relation.
036     *
037     * @param multipolygon the multipolygon
038     */
039    public DefaultGeoProperty(Relation multipolygon) {
040        this.area = Geometry.getAreaLatLon(multipolygon);
041    }
042
043    @Override
044    public Boolean get(LatLon ll) {
045        return area.contains(ll.lon(), ll.lat());
046    }
047
048    @Override
049    public Boolean get(BBox box) {
050        Area abox = new Area(box.toRectangle());
051        Geometry.PolygonIntersection is = Geometry.polygonIntersection(abox, area, 1e-10 /* using deg and not meters */);
052        switch (is) {
053            case FIRST_INSIDE_SECOND:
054                return Boolean.TRUE;
055            case OUTSIDE:
056                return Boolean.FALSE;
057            default:
058                return null;
059        }
060    }
061
062    /**
063     * Returns the area.
064     * @return the area
065     * @since 14484
066     */
067    public final Area getArea() {
068        return area;
069    }
070}