source: josm/trunk/src/org/openstreetmap/josm/actions/SelectByInternalPointAction.java@ 13437

Last change on this file since 13437 was 13434, checked in by Don-vip, 6 years ago

see #8039, see #10456 - support read-only data layers

  • Property svn:eol-style set to native
File size: 5.1 KB
RevLine 
[7144]1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
[7828]4import java.util.ArrayList;
5import java.util.Collection;
[7921]6import java.util.Collections;
[8338]7import java.util.Map;
[7828]8import java.util.TreeMap;
9
[7144]10import org.openstreetmap.josm.data.coor.EastNorth;
11import org.openstreetmap.josm.data.osm.BBox;
[7921]12import org.openstreetmap.josm.data.osm.DataSet;
[7144]13import org.openstreetmap.josm.data.osm.Node;
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.osm.Relation;
16import org.openstreetmap.josm.data.osm.RelationMember;
17import org.openstreetmap.josm.data.osm.Way;
[12630]18import org.openstreetmap.josm.data.projection.Projection;
19import org.openstreetmap.josm.gui.MainApplication;
[7144]20import org.openstreetmap.josm.tools.Geometry;
21
22/**
[8114]23 * This allows to select a polygon/multipolygon by an internal point.
24 * @since 7144
[7144]25 */
[9594]26public final class SelectByInternalPointAction {
[7144]27
[9594]28 private SelectByInternalPointAction() {
29 // Hide public constructor for utility class
30 }
31
[7144]32 /**
[11240]33 * Returns the surrounding polygons/multipolygons ordered by their area size (from small to large)
[7144]34 * which contain the internal point.
35 *
36 * @param internalPoint the internal point.
[8114]37 * @return the surrounding polygons/multipolygons
[7144]38 */
39 public static Collection<OsmPrimitive> getSurroundingObjects(EastNorth internalPoint) {
[13434]40 return getSurroundingObjects(MainApplication.getLayerManager().getActiveDataSet(), internalPoint, false);
[11240]41 }
42
43 /**
44 * Returns the surrounding polygons/multipolygons ordered by their area size (from small to large)
45 * which contain the internal point.
46 *
47 * @param ds the data set
48 * @param internalPoint the internal point.
[11247]49 * @param includeMultipolygonWays whether to include multipolygon ways in the result (false by default)
[11240]50 * @return the surrounding polygons/multipolygons
[11247]51 * @since 11247
[11240]52 */
[11247]53 public static Collection<OsmPrimitive> getSurroundingObjects(DataSet ds, EastNorth internalPoint, boolean includeMultipolygonWays) {
[7921]54 if (ds == null) {
55 return Collections.emptySet();
56 }
[7144]57 final Node n = new Node(internalPoint);
[8338]58 final Map<Double, OsmPrimitive> found = new TreeMap<>();
[7921]59 for (Way w : ds.getWays()) {
[9594]60 if (w.isUsable() && w.isClosed() && w.isSelectable() && Geometry.nodeInsidePolygon(n, w.getNodes())) {
61 found.put(Geometry.closedWayArea(w), w);
[7144]62 }
63 }
[12630]64 Projection projection = MainApplication.getMap().mapView.getProjection();
[7921]65 for (Relation r : ds.getRelations()) {
[9594]66 if (r.isUsable() && r.isMultipolygon() && r.isSelectable() && Geometry.isNodeInsideMultiPolygon(n, r, null)) {
[11247]67 if (!includeMultipolygonWays) {
68 for (RelationMember m : r.getMembers()) {
69 if (m.isWay() && m.getWay().isClosed()) {
70 found.values().remove(m.getWay());
71 }
[7144]72 }
73 }
[9594]74 // estimate multipolygon size by its bounding box area
75 BBox bBox = r.getBBox();
[12630]76 EastNorth en1 = projection.latlon2eastNorth(bBox.getTopLeft());
77 EastNorth en2 = projection.latlon2eastNorth(bBox.getBottomRight());
[9594]78 double s = Math.abs((en1.east() - en2.east()) * (en1.north() - en2.north()));
79 found.put(s <= 0 ? 1e8 : s, r);
[7144]80 }
81 }
82 return found.values();
83 }
84
85 /**
[8114]86 * Returns the smallest surrounding polygon/multipolygon which contains the internal point.
[7144]87 *
88 * @param internalPoint the internal point.
[8114]89 * @return the smallest surrounding polygon/multipolygon
[7144]90 */
91 public static OsmPrimitive getSmallestSurroundingObject(EastNorth internalPoint) {
92 final Collection<OsmPrimitive> surroundingObjects = getSurroundingObjects(internalPoint);
93 return surroundingObjects.isEmpty() ? null : surroundingObjects.iterator().next();
94 }
95
96 /**
[7828]97 * Select a polygon or multipolygon by an internal point.
[7144]98 *
99 * @param internalPoint the internal point.
100 * @param doAdd whether to add selected polygon to the current selection.
101 * @param doRemove whether to remove the selected polygon from the current selection.
102 */
103 public static void performSelection(EastNorth internalPoint, boolean doAdd, boolean doRemove) {
104 final Collection<OsmPrimitive> surroundingObjects = getSurroundingObjects(internalPoint);
[13434]105 final DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
[7144]106 if (surroundingObjects.isEmpty()) {
107 return;
108 } else if (doRemove) {
[9594]109 final Collection<OsmPrimitive> newSelection = new ArrayList<>(ds.getSelected());
[7144]110 newSelection.removeAll(surroundingObjects);
[9594]111 ds.setSelected(newSelection);
[7144]112 } else if (doAdd) {
[9594]113 final Collection<OsmPrimitive> newSelection = new ArrayList<>(ds.getSelected());
[7144]114 newSelection.add(surroundingObjects.iterator().next());
[9594]115 ds.setSelected(newSelection);
[7144]116 } else {
[9594]117 ds.setSelected(surroundingObjects.iterator().next());
[7144]118 }
119 }
120}
Note: See TracBrowser for help on using the repository browser.