source: josm/src/org/openstreetmap/josm/gui/NavigatableComponent.java@ 71

Last change on this file since 71 was 71, checked in by imi, 18 years ago
  • refactored GpsPoint to be immutable and added LatLon and NorthEast
  • refactored Bounding Box calculations
  • various other renames
File size: 7.5 KB
Line 
1package org.openstreetmap.josm.gui;
2
3import java.awt.Point;
4import java.util.Collection;
5import java.util.HashSet;
6
7import javax.swing.JComponent;
8
9import org.openstreetmap.josm.Main;
10import org.openstreetmap.josm.data.coor.LatLon;
11import org.openstreetmap.josm.data.coor.EastNorth;
12import org.openstreetmap.josm.data.osm.LineSegment;
13import org.openstreetmap.josm.data.osm.Node;
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.osm.Way;
16import org.openstreetmap.josm.data.projection.Projection;
17
18/**
19 * An component that can be navigated by a mapmover. Used as map view and for the
20 * zoomer in the download dialog.
21 *
22 * @author imi
23 */
24public class NavigatableComponent extends JComponent {
25
26 /**
27 * The scale factor in x or y-units per pixel. This means, if scale = 10,
28 * every physical pixel on screen are 10 x or 10 y units in the
29 * northing/easting space of the projection.
30 */
31 protected double scale;
32 /**
33 * Center n/e coordinate of the desired screen center.
34 */
35 protected EastNorth center;
36
37 /**
38 * Return the current scale value.
39 * @return The scale value currently used in display
40 */
41 public double getScale() {
42 return scale;
43 }
44
45 /**
46 * @return Returns the center point. A copy is returned, so users cannot
47 * change the center by accessing the return value. Use zoomTo instead.
48 */
49 public EastNorth getCenter() {
50 return center;
51 }
52
53 /**
54 * @param x X-Pixelposition to get coordinate from
55 * @param y Y-Pixelposition to get coordinate from
56 *
57 * @return Geographic coordinates from a specific pixel coordination
58 * on the screen.
59 */
60 public EastNorth getEastNorth(int x, int y) {
61 return new EastNorth(
62 center.east() + (x - getWidth()/2.0)*scale,
63 center.north() - (y - getHeight()/2.0)*scale);
64 }
65
66 /**
67 * @param x X-Pixelposition to get coordinate from
68 * @param y Y-Pixelposition to get coordinate from
69 *
70 * @return Geographic unprojected coordinates from a specific pixel coordination
71 * on the screen.
72 */
73 public LatLon getLatLon(int x, int y) {
74 EastNorth eastNorth = new EastNorth(
75 center.east() + (x - getWidth()/2.0)*scale,
76 center.north() - (y - getHeight()/2.0)*scale);
77 return Main.pref.getProjection().eastNorth2latlon(eastNorth);
78 }
79
80 /**
81 * Return the point on the screen where this Coordinate would be.
82 * @param point The point, where this geopoint would be drawn.
83 * @return The point on screen where "point" would be drawn, relative
84 * to the own top/left.
85 */
86 public Point getPoint(EastNorth p) {
87 double x = (p.east()-center.east())/scale + getWidth()/2;
88 double y = (center.north()-p.north())/scale + getHeight()/2;
89 return new Point((int)x,(int)y);
90 }
91
92 /**
93 * Zoom to the given coordinate.
94 * @param centerX The center x-value (easting) to zoom to.
95 * @param centerY The center y-value (northing) to zoom to.
96 * @param scale The scale to use.
97 */
98 public void zoomTo(EastNorth newCenter, double scale) {
99 center = newCenter;
100 getProjection().eastNorth2latlon(center);
101 this.scale = scale;
102 repaint();
103 }
104
105 /**
106 * Return the object, that is nearest to the given screen point.
107 *
108 * First, a node will be searched. If a node within 10 pixel is found, the
109 * nearest node is returned.
110 *
111 * If no node is found, search for pending line segments.
112 *
113 * If no such line segment is found, and a non-pending line segment is
114 * within 10 pixel to p, this segment is returned, except when
115 * <code>wholeWay</code> is <code>true</code>, in which case the
116 * corresponding Way is returned.
117 *
118 * If no line segment is found and the point is within an area, return that
119 * area.
120 *
121 * If no area is found, return <code>null</code>.
122 *
123 * @param p The point on screen.
124 * @param segmentInsteadWay Whether the line segment (true) or only the whole
125 * way should be returned.
126 * @return The primitive, that is nearest to the point p.
127 */
128 public OsmPrimitive getNearest(Point p, boolean segmentInsteadWay) {
129 double minDistanceSq = Double.MAX_VALUE;
130 OsmPrimitive minPrimitive = null;
131
132 // nodes
133 for (Node n : Main.main.ds.nodes) {
134 if (n.isDeleted())
135 continue;
136 Point sp = getPoint(n.eastNorth);
137 double dist = p.distanceSq(sp);
138 if (minDistanceSq > dist && dist < 100) {
139 minDistanceSq = p.distanceSq(sp);
140 minPrimitive = n;
141 }
142 }
143 if (minPrimitive != null)
144 return minPrimitive;
145
146 // for whole ways, try the ways first
147 minDistanceSq = Double.MAX_VALUE;
148 if (!segmentInsteadWay) {
149 for (Way w : Main.main.ds.ways) {
150 if (w.isDeleted())
151 continue;
152 for (LineSegment ls : w.segments) {
153 if (ls.isDeleted() || ls.incomplete)
154 continue;
155 Point A = getPoint(ls.from.eastNorth);
156 Point B = getPoint(ls.to.eastNorth);
157 double c = A.distanceSq(B);
158 double a = p.distanceSq(B);
159 double b = p.distanceSq(A);
160 double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
161 if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
162 minDistanceSq = perDist;
163 minPrimitive = w;
164 }
165 }
166 }
167 if (minPrimitive != null)
168 return minPrimitive;
169 }
170
171 minDistanceSq = Double.MAX_VALUE;
172 // line segments
173 for (LineSegment ls : Main.main.ds.lineSegments) {
174 if (ls.isDeleted() || ls.incomplete)
175 continue;
176 Point A = getPoint(ls.from.eastNorth);
177 Point B = getPoint(ls.to.eastNorth);
178 double c = A.distanceSq(B);
179 double a = p.distanceSq(B);
180 double b = p.distanceSq(A);
181 double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
182 if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
183 minDistanceSq = perDist;
184 minPrimitive = ls;
185 }
186 }
187
188 return minPrimitive;
189 }
190
191 /**
192 * @return A list of all objects that are nearest to
193 * the mouse. To do this, first the nearest object is
194 * determined.
195 *
196 * If its a node, return all line segments and
197 * streets the node is part of, as well as all nodes
198 * (with their line segments and ways) with the same
199 * location.
200 *
201 * If its a line segment, return all ways this segment
202 * belongs to as well as all line segments that are between
203 * the same nodes (in both direction) with all their ways.
204 *
205 * @return A collection of all items or <code>null</code>
206 * if no item under or near the point. The returned
207 * list is never empty.
208 */
209 public Collection<OsmPrimitive> getAllNearest(Point p) {
210 OsmPrimitive osm = getNearest(p, true);
211 if (osm == null)
212 return null;
213 Collection<OsmPrimitive> c = new HashSet<OsmPrimitive>();
214 c.add(osm);
215 if (osm instanceof Node) {
216 Node node = (Node)osm;
217 for (Node n : Main.main.ds.nodes)
218 if (!n.isDeleted() && n.coor.equals(node.coor))
219 c.add(n);
220 for (LineSegment ls : Main.main.ds.lineSegments)
221 // line segments never match nodes, so they are skipped by contains
222 if (!ls.isDeleted() && !ls.incomplete && (c.contains(ls.from) || c.contains(ls.to)))
223 c.add(ls);
224 }
225 if (osm instanceof LineSegment) {
226 LineSegment line = (LineSegment)osm;
227 for (LineSegment ls : Main.main.ds.lineSegments)
228 if (!ls.isDeleted() && ls.equalPlace(line))
229 c.add(ls);
230 }
231 if (osm instanceof Node || osm instanceof LineSegment) {
232 for (Way t : Main.main.ds.ways) {
233 if (t.isDeleted())
234 continue;
235 for (LineSegment ls : t.segments) {
236 if (!ls.isDeleted() && !ls.incomplete && c.contains(ls)) {
237 c.add(t);
238 break;
239 }
240 }
241 }
242 }
243 return c;
244 }
245
246 /**
247 * @return The projection to be used in calculating stuff.
248 */
249 protected Projection getProjection() {
250 return Main.pref.getProjection();
251 }
252}
Note: See TracBrowser for help on using the repository browser.