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

Last change on this file since 11885 was 11247, checked in by Don-vip, 7 years ago

see #9400 - see #10387 - see #12914 - initial implementation of boundaries file, replacing left-right-hand-traffic.osm, discourage contributors to use operator=RFF and operator=ERDF in France (territories rules must be manually eabled on existing installations)

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