source: josm/src/org/openstreetmap/josm/command/DataSet.java@ 21

Last change on this file since 21 was 21, checked in by imi, 19 years ago
  • started command implementation
  • cleaned up Layer
  • gpsbabel style for importing qpegps tracks
File size: 8.1 KB
Line 
1package org.openstreetmap.josm.command;
2
3import java.util.Collection;
4import java.util.Collections;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.Iterator;
8import java.util.LinkedList;
9import java.util.Map;
10import java.util.Set;
11
12import org.openstreetmap.josm.data.Bounds;
13import org.openstreetmap.josm.data.SelectionTracker;
14import org.openstreetmap.josm.data.osm.LineSegment;
15import org.openstreetmap.josm.data.osm.Node;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.Track;
18
19/**
20 * DataSet is the data behind one window in the application. It can consist of only a few
21 * points up to the whole osm database. DataSet's can be merged together, split up into
22 * several different ones, saved, (up/down/disk)loaded etc.
23 *
24 * Note, that DataSet is not an osm-primitive, it is not within
25 * org.openstreetmap.josm.data.osm and has no key association but a few
26 * members to store some information.
27 *
28 * @author imi
29 */
30public class DataSet extends SelectionTracker implements Cloneable {
31
32 /**
33 * All nodes goes here, even when included in other data (tracks etc).
34 * This enables the instant conversion of the whole DataSet by iterating over
35 * this data structure.
36 */
37 public Collection<Node> nodes = new LinkedList<Node>();
38
39 /**
40 * All pending line segments goes here. Pending line segments are those, that
41 * are in this list but are in no track.
42 */
43 Collection<LineSegment> pendingLineSegments = new LinkedList<LineSegment>();
44
45 /**
46 * All tracks (Streets etc.) in the DataSet.
47 *
48 * The nodes of the track segments of this track must be objects from
49 * the nodes list, however the track segments are stored only in the
50 * track list.
51 */
52 Collection<Track> tracks = new LinkedList<Track>();
53
54 /**
55 * Add the track to the tracklist.
56 */
57 public void addTrack(Track t) {
58 tracks.add(t);
59 }
60 /**
61 * Remove the track from the tracklist.
62 */
63 public void removeTrack(Track t) {
64 t.destroy();
65 tracks.remove(t);
66 }
67 /**
68 * Return a read-only collection of all tracks
69 */
70 public Collection<Track> tracks() {
71 return Collections.unmodifiableCollection(tracks);
72 }
73
74 /**
75 * Add a newly created line segment to the pending lines list.
76 */
77 public void addPendingLineSegment(LineSegment ls) {
78 pendingLineSegments.add(ls);
79 }
80 /**
81 * Remove a line segment from the pending lines list, because it has been
82 * assigned to the track.
83 * @param ls The line segment from the pending list
84 * @param t The track, that will hold the line segment
85 * @param end <code>true</code> to attach on the end. <code>false</code>
86 * to attach on the beginning.
87 */
88 public void assignPendingLineSegment(LineSegment ls, Track t, boolean end) {
89 pendingLineSegments.remove(ls);
90 if (end)
91 t.add(ls);
92 else
93 t.addStart(ls);
94 }
95 /**
96 * Delete the pending line segment without moving it anywhere.
97 */
98 public void destroyPendingLineSegment(LineSegment ls) {
99 pendingLineSegments.remove(ls);
100 ls.destroy();
101 }
102 /**
103 * Return an read-only iterator over all pending line segments.
104 */
105 public Collection<LineSegment> pendingLineSegments() {
106 return Collections.unmodifiableCollection(pendingLineSegments);
107 }
108
109 /**
110 * Return the bounds of this DataSet, depending on X/Y values.
111 * The min of the return value is the upper left GeoPoint, the max the lower
112 * down GeoPoint, regarding to the X/Y values.
113 *
114 * Return null, if any point not converted yet or if there are no points at all.
115 *
116 * @return Bounding coordinate structure.
117 */
118 public Bounds getBoundsXY() {
119 if (nodes.isEmpty())
120 return null;
121
122 Node first = nodes.iterator().next();
123 Bounds b = new Bounds(first.coor.clone(), first.coor.clone());
124 for (Node w : nodes)
125 {
126 if (Double.isNaN(w.coor.x) || Double.isNaN(w.coor.y))
127 return null;
128 if (w.coor.x < b.min.x)
129 b.min.x = w.coor.x;
130 if (w.coor.y < b.min.y)
131 b.min.y = w.coor.y;
132 if (w.coor.x > b.max.x)
133 b.max.x = w.coor.x;
134 if (w.coor.y > b.max.y)
135 b.max.y = w.coor.y;
136 }
137 return b;
138 }
139
140 /**
141 * Return the bounds of this DataSet, depending on lat/lon values.
142 * The min of the return value is the upper left GeoPoint, the max the lower
143 * down GeoPoint.
144 *
145 * Return null, if any point does not have lat/lon or if there are no
146 * points at all.
147 *
148 * @return Bounding coordinate structure.
149 */
150 public Bounds getBoundsLatLon() {
151 if (nodes.isEmpty())
152 return null;
153
154 Node first = nodes.iterator().next();
155 Bounds b = new Bounds(first.coor.clone(), first.coor.clone());
156 for (Node w : nodes)
157 {
158 if (Double.isNaN(w.coor.lat) || Double.isNaN(w.coor.lon))
159 return null;
160 if (w.coor.lat < b.min.lat)
161 b.min.lat = w.coor.lat;
162 if (w.coor.lon < b.min.lon)
163 b.min.lon = w.coor.lon;
164 if (w.coor.lat > b.max.lat)
165 b.max.lat = w.coor.lat;
166 if (w.coor.lon > b.max.lon)
167 b.max.lon = w.coor.lon;
168 }
169 return b;
170 }
171
172 /**
173 * Remove the selection of the whole dataset.
174 */
175 public void clearSelection() {
176 clearSelection(nodes);
177 clearSelection(tracks);
178 for (Track t : tracks)
179 clearSelection(t.segments());
180 }
181
182 /**
183 * Return a list of all selected objects. Even keys are returned.
184 * @return List of all selected objects.
185 */
186 @Override
187 public Collection<OsmPrimitive> getSelected() {
188 Collection<OsmPrimitive> sel = getSelected(nodes);
189 sel.addAll(getSelected(pendingLineSegments));
190 sel.addAll(getSelected(tracks));
191 for (Track t : tracks)
192 sel.addAll(getSelected(t.segments()));
193 return sel;
194 }
195
196 /**
197 * Import the given dataset by merging all data with this dataset.
198 * The objects imported are not cloned, so from now on, these data belong
199 * to both datasets. So use mergeFrom only if you are about to abandon the
200 * other dataset or this dataset.
201 *
202 * @param ds The DataSet to merge into this one.
203 * @param mergeEqualNodes If <code>true</code>, nodes with the same lat/lon
204 * are merged together.
205 */
206 public void mergeFrom(DataSet ds, boolean mergeEqualNodes) {
207 System.out.println(nodes.size()+" "+pendingLineSegments.size()+" "+tracks.size());
208 if (mergeEqualNodes) {
209 Map<Node, Node> mergeMap = new HashMap<Node, Node>();
210 Set<Node> nodesToAdd = new HashSet<Node>();
211 for (Node n : nodes) {
212 for (Iterator<Node> it = ds.nodes.iterator(); it.hasNext();) {
213 Node dsn = it.next();
214 if (n.coor.equalsLatLon(dsn.coor)) {
215 mergeMap.put(dsn, n);
216 n.mergeFrom(dsn);
217 it.remove();
218 } else {
219 nodesToAdd.add(dsn);
220 }
221 }
222 }
223 nodes.addAll(nodesToAdd);
224 for (Track t : ds.tracks) {
225 for (LineSegment ls : t.segments()) {
226 Node n = mergeMap.get(ls.getStart());
227 if (n != null)
228 ls.start = n;
229 n = mergeMap.get(ls.getEnd());
230 if (n != null)
231 ls.end = n;
232 }
233 }
234 tracks.addAll(ds.tracks);
235 for (LineSegment ls : ds.pendingLineSegments) {
236 Node n = mergeMap.get(ls.getStart());
237 if (n != null)
238 ls.start = n;
239 n = mergeMap.get(ls.getEnd());
240 if (n != null)
241 ls.end = n;
242 }
243 pendingLineSegments.addAll(ds.pendingLineSegments);
244 } else {
245 nodes.addAll(ds.nodes);
246 tracks.addAll(ds.tracks);
247 pendingLineSegments.addAll(ds.pendingLineSegments);
248 }
249 System.out.println(nodes.size()+" "+pendingLineSegments.size()+" "+tracks.size());
250 }
251
252 /**
253 * Remove the selection from every value in the collection.
254 * @param list The collection to remove the selection from.
255 */
256 private void clearSelection(Collection<? extends OsmPrimitive> list) {
257 if (list == null)
258 return;
259 for (OsmPrimitive osm : list) {
260 osm.setSelected(false, this);
261 if (osm.keys != null)
262 clearSelection(osm.keys.keySet());
263 }
264 }
265
266 /**
267 * Return all selected items in the collection.
268 * @param list The collection from which the selected items are returned.
269 */
270 private Collection<OsmPrimitive> getSelected(Collection<? extends OsmPrimitive> list) {
271 Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
272 if (list == null)
273 return sel;
274 for (OsmPrimitive osm : list) {
275 if (osm.isSelected())
276 sel.add(osm);
277 if (osm.keys != null)
278 sel.addAll(getSelected(osm.keys.keySet()));
279 }
280 return sel;
281 }
282
283
284 @Override
285 public DataSet clone() {
286 try {return (DataSet)super.clone();} catch (CloneNotSupportedException e) {}
287 return null;
288 }
289}
Note: See TracBrowser for help on using the repository browser.