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}