source: josm/trunk/src/org/openstreetmap/josm/data/imagery/OffsetBookmark.java@ 12093

Last change on this file since 12093 was 12093, checked in by bastiK, 7 years ago

fixed #14734 - Handling imagery offsets when reprojecting

  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.imagery;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.Collections;
9import java.util.List;
10import java.util.ListIterator;
11
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.data.Preferences.pref;
14import org.openstreetmap.josm.data.Preferences.writeExplicitly;
15import org.openstreetmap.josm.data.coor.EastNorth;
16import org.openstreetmap.josm.data.coor.LatLon;
17import org.openstreetmap.josm.data.projection.Projection;
18import org.openstreetmap.josm.data.projection.Projections;
19import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
20import org.openstreetmap.josm.gui.layer.ImageryLayer;
21
22/**
23 * Class to save a displacement of background imagery as a bookmark.
24 *
25 * Known offset bookmarks will be stored in the preferences and can be
26 * restored by the user in later sessions.
27 */
28public class OffsetBookmark {
29 private static final List<OffsetBookmark> allBookmarks = new ArrayList<>();
30
31 @pref private String projection_code;
32 @pref private String imagery_name;
33 @pref private String name;
34 @pref @writeExplicitly private double dx, dy;
35 @pref private double center_lon, center_lat;
36
37 public boolean isUsable(ImageryLayer layer) {
38 if (projection_code == null) return false;
39 if (!Main.getProjection().toCode().equals(projection_code) && !hasCenter()) return false;
40 return layer.getInfo().getName().equals(imagery_name);
41 }
42
43 /**
44 * Construct new empty OffsetBookmark.
45 *
46 * Only used for preferences handling.
47 */
48 public OffsetBookmark() {
49 // do nothing
50 }
51
52 public OffsetBookmark(String projectionCode, String imageryName, String name, double dx, double dy) {
53 this(projectionCode, imageryName, name, dx, dy, 0, 0);
54 }
55
56 public OffsetBookmark(String projectionCode, String imageryName, String name, double dx, double dy, double centerLon, double centerLat) {
57 this.projection_code = projectionCode;
58 this.imagery_name = imageryName;
59 this.name = name;
60 this.dx = dx;
61 this.dy = dy;
62 this.center_lon = centerLon;
63 this.center_lat = centerLat;
64 }
65
66 public OffsetBookmark(Collection<String> list) {
67 List<String> array = new ArrayList<>(list);
68 this.projection_code = array.get(0);
69 this.imagery_name = array.get(1);
70 this.name = array.get(2);
71 this.dx = Double.parseDouble(array.get(3));
72 this.dy = Double.parseDouble(array.get(4));
73 if (array.size() >= 7) {
74 this.center_lon = Double.parseDouble(array.get(5));
75 this.center_lat = Double.parseDouble(array.get(6));
76 }
77 if (projection_code == null) {
78 Main.error(tr("Projection ''{0}'' is not found, bookmark ''{1}'' is not usable", projection_code, name));
79 }
80 }
81
82 public String getProjectionCode() {
83 return projection_code;
84 }
85
86 public String getName() {
87 return name;
88 }
89
90 public String getImageryName() {
91 return imagery_name;
92 }
93
94 /**
95 * Get displacement in EastNorth coordinates of the original projection.
96 *
97 * @see #getProjectionCode()
98 * @return the displacement
99 */
100 public EastNorth getDisplacement() {
101 return new EastNorth(dx, dy);
102 }
103
104 /**
105 * Get displacement in EastNorth coordinates of a given projection.
106 *
107 * Displacement will be converted to the given projection, with respect to the
108 * center (reference point) of this bookmark.
109 * @param proj the projection
110 * @return the displacement, converted to that projection
111 */
112 public EastNorth getDisplacement(Projection proj) {
113 if (proj.toCode().equals(projection_code)) {
114 return getDisplacement();
115 }
116 LatLon center = getCenter();
117 Projection offsetProj = Projections.getProjectionByCode(projection_code);
118 EastNorth centerEN = offsetProj.latlon2eastNorth(center);
119 EastNorth shiftedEN = centerEN.add(getDisplacement());
120 LatLon shifted = offsetProj.eastNorth2latlon(shiftedEN);
121 EastNorth centerEN2 = proj.latlon2eastNorth(center);
122 EastNorth shiftedEN2 = proj.latlon2eastNorth(shifted);
123 return shiftedEN2.subtract(centerEN2);
124 }
125
126 /**
127 * Get center/reference point of the bookmark.
128 *
129 * Basically this is the place where it was created and is valid.
130 * The center may be unrecorded (see {@link #hasCenter()), in which
131 * case a dummy center (0,0) will be returned.
132 * @return the center
133 */
134 public LatLon getCenter() {
135 return new LatLon(center_lat, center_lon);
136 }
137
138 /**
139 * Check if bookmark has a valid center.
140 * @return true if bookmark has a valid center
141 */
142 public boolean hasCenter() {
143 return center_lat != 0 || center_lon != 0;
144 }
145
146 public void setProjectionCode(String projectionCode) {
147 this.projection_code = projectionCode;
148 }
149
150 public void setName(String name) {
151 this.name = name;
152 }
153
154 public void setImageryName(String imageryName) {
155 this.imagery_name = imageryName;
156 }
157
158 public void setDisplacement(EastNorth displacement) {
159 this.dx = displacement.east();
160 this.dy = displacement.north();
161 }
162
163 public static void loadBookmarks() {
164 List<OffsetBookmark> bookmarks = Main.pref.getListOfStructs("imagery.offsetbookmarks", null, OffsetBookmark.class);
165 if (bookmarks == null) {
166 loadBookmarksOld();
167 saveBookmarks();
168 } else {
169 allBookmarks.addAll(bookmarks);
170 }
171 }
172
173 // migration code - remove Nov. 2017
174 private static void loadBookmarksOld() {
175 for (Collection<String> c : Main.pref.getArray("imagery.offsets",
176 Collections.<Collection<String>>emptySet())) {
177 allBookmarks.add(new OffsetBookmark(c));
178 }
179 }
180
181 public static void saveBookmarks() {
182 Main.pref.putListOfStructs("imagery.offsetbookmarks", allBookmarks, OffsetBookmark.class);
183 }
184
185 /**
186 * Returns all bookmarks.
187 * @return all bookmarks (unmodifiable collection)
188 * @since 11651
189 */
190 public static List<OffsetBookmark> getBookmarks() {
191 return Collections.unmodifiableList(allBookmarks);
192 }
193
194 /**
195 * Returns the number of bookmarks.
196 * @return the number of bookmarks
197 * @since 11651
198 */
199 public static int getBookmarksSize() {
200 return allBookmarks.size();
201 }
202
203 /**
204 * Adds a bookmark.
205 * @param ob bookmark to add
206 * @return {@code true}
207 * @since 11651
208 */
209 public static boolean addBookmark(OffsetBookmark ob) {
210 return allBookmarks.add(ob);
211 }
212
213 /**
214 * Removes a bookmark.
215 * @param ob bookmark to remove
216 * @return {@code true} if this list contained the specified element
217 * @since 11651
218 */
219 public static boolean removeBookmark(OffsetBookmark ob) {
220 return allBookmarks.remove(ob);
221 }
222
223 /**
224 * Returns the bookmark at the given index.
225 * @param index bookmark index
226 * @return the bookmark at the given index
227 * @throws IndexOutOfBoundsException if the index is out of range
228 * (<tt>index &lt; 0 || index &gt;= size()</tt>)
229 * @since 11651
230 */
231 public static OffsetBookmark getBookmarkByIndex(int index) {
232 return allBookmarks.get(index);
233 }
234
235 public static OffsetBookmark getBookmarkByName(ImageryLayer layer, String name) {
236 for (OffsetBookmark b : allBookmarks) {
237 if (b.isUsable(layer) && name.equals(b.name))
238 return b;
239 }
240 return null;
241 }
242
243 public static void bookmarkOffset(String name, AbstractTileSourceLayer layer) {
244 LatLon center;
245 if (Main.isDisplayingMapView()) {
246 center = Main.getProjection().eastNorth2latlon(Main.map.mapView.getCenter());
247 } else {
248 center = LatLon.ZERO;
249 }
250 OffsetBookmark nb = new OffsetBookmark(
251 Main.getProjection().toCode(), layer.getInfo().getName(),
252 name, layer.getDisplaySettings().getDx(), layer.getDisplaySettings().getDy(), center.lon(), center.lat());
253 for (ListIterator<OffsetBookmark> it = allBookmarks.listIterator(); it.hasNext();) {
254 OffsetBookmark b = it.next();
255 if (b.isUsable(layer) && name.equals(b.name)) {
256 it.set(nb);
257 saveBookmarks();
258 return;
259 }
260 }
261 allBookmarks.add(nb);
262 saveBookmarks();
263 }
264}
Note: See TracBrowser for help on using the repository browser.