| | 1 | package org.openstreetmap.josm.actions; |
| | 2 | |
| | 3 | import org.openstreetmap.josm.Main; |
| | 4 | import org.openstreetmap.josm.data.coor.EastNorth; |
| | 5 | import org.openstreetmap.josm.data.osm.BBox; |
| | 6 | import org.openstreetmap.josm.data.osm.Node; |
| | 7 | import org.openstreetmap.josm.data.osm.OsmPrimitive; |
| | 8 | import org.openstreetmap.josm.data.osm.Relation; |
| | 9 | import org.openstreetmap.josm.data.osm.RelationMember; |
| | 10 | import org.openstreetmap.josm.data.osm.Way; |
| | 11 | import org.openstreetmap.josm.tools.Geometry; |
| | 12 | |
| | 13 | import java.awt.event.ActionEvent; |
| | 14 | import java.util.ArrayList; |
| | 15 | import java.util.Collection; |
| | 16 | import java.util.TreeMap; |
| | 17 | |
| | 18 | public class SelectByInternalAction extends JosmAction { |
| | 19 | |
| | 20 | /** |
| | 21 | * Returns the surrounding objects ordered by their size (ascending). |
| | 22 | */ |
| | 23 | public static Collection<OsmPrimitive> getSurroundingObjects(EastNorth internalPoint) { |
| | 24 | final Node n = new Node(internalPoint); |
| | 25 | TreeMap<Double, OsmPrimitive> found = new TreeMap<>(); |
| | 26 | for (Way w : getCurrentDataSet().getWays()) { |
| | 27 | if (w.isUsable() && w.isClosed()) { |
| | 28 | if (Geometry.nodeInsidePolygon(n, w.getNodes())) { |
| | 29 | found.put(Geometry.closedWayArea(w), w); |
| | 30 | } |
| | 31 | } |
| | 32 | } |
| | 33 | for (Relation r : getCurrentDataSet().getRelations()) { |
| | 34 | if (r.isUsable() && r.isMultipolygon()) { |
| | 35 | if (Geometry.isNodeInsideMultiPolygon(n, r, null)) { |
| | 36 | for (RelationMember m : r.getMembers()) { |
| | 37 | if (m.isWay() && m.getWay().isClosed()) { |
| | 38 | found.values().remove(m.getWay()); |
| | 39 | } |
| | 40 | } |
| | 41 | // estimate multipolygon size by its bounding box area |
| | 42 | BBox bBox = r.getBBox(); |
| | 43 | EastNorth en1 = Main.map.mapView.getProjection().latlon2eastNorth(bBox.getTopLeft()); |
| | 44 | EastNorth en2 = Main.map.mapView.getProjection().latlon2eastNorth(bBox.getBottomRight()); |
| | 45 | double s = Math.abs((en1.east() - en2.east()) * (en1.north() - en2.north())); |
| | 46 | if (s == 0) s = 1e8; |
| | 47 | found.put(s, r); |
| | 48 | } |
| | 49 | } |
| | 50 | } |
| | 51 | |
| | 52 | return found.values(); |
| | 53 | } |
| | 54 | |
| | 55 | |
| | 56 | /** |
| | 57 | * Returns the smallest surrounding object. |
| | 58 | */ |
| | 59 | public static OsmPrimitive getSmallestSurroundingObject(EastNorth internalPoint) { |
| | 60 | final Collection<OsmPrimitive> surroundingObjects = getSurroundingObjects(internalPoint); |
| | 61 | return surroundingObjects.isEmpty() ? null : surroundingObjects.iterator().next(); |
| | 62 | } |
| | 63 | |
| | 64 | public static void performSelection(EastNorth internalPoint, boolean doAdd, boolean doRemove) { |
| | 65 | final Collection<OsmPrimitive> surroundingObjects = getSurroundingObjects(internalPoint); |
| | 66 | if (surroundingObjects.isEmpty()) { |
| | 67 | return; |
| | 68 | } else if (doRemove) { |
| | 69 | final Collection<OsmPrimitive> newSelection = new ArrayList<>(getCurrentDataSet().getSelected()); |
| | 70 | newSelection.removeAll(surroundingObjects); |
| | 71 | getCurrentDataSet().setSelected(newSelection); |
| | 72 | } else if (doAdd) { |
| | 73 | final Collection<OsmPrimitive> newSelection = new ArrayList<>(getCurrentDataSet().getSelected()); |
| | 74 | newSelection.add(surroundingObjects.iterator().next()); |
| | 75 | getCurrentDataSet().setSelected(newSelection); |
| | 76 | } else { |
| | 77 | getCurrentDataSet().setSelected(surroundingObjects.iterator().next()); |
| | 78 | } |
| | 79 | } |
| | 80 | |
| | 81 | @Override |
| | 82 | public void actionPerformed(ActionEvent e) { |
| | 83 | } |
| | 84 | } |