source: josm/trunk/src/org/openstreetmap/josm/data/osm/Way.java@ 2252

Last change on this file since 2252 was 2252, checked in by Gubaer, 15 years ago

Refactored JOSM help system, slightly extended
Fixed problem with new internal representation of nodes as array (in Way)

  • Property svn:eol-style set to native
File size: 8.1 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.data.osm;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Arrays;
8import java.util.Collection;
9import java.util.List;
10
11import org.openstreetmap.josm.data.osm.visitor.Visitor;
12import org.openstreetmap.josm.tools.CopyList;
13import org.openstreetmap.josm.tools.Pair;
14
15/**
16 * One full way, consisting of a list of way nodes.
17 *
18 * @author imi
19 */
20public final class Way extends OsmPrimitive {
21
22 /**
23 * All way nodes in this way
24 *
25 */
26 private Node[] nodes = new Node[0];
27
28 /**
29 *
30 * You can modify returned list but changes will not be propagated back
31 * to the Way. Use {@link #setNodes(List)} to update this way
32 * @return Nodes composing the way
33 * @since 1862
34 */
35 public List<Node> getNodes() {
36 return new CopyList<Node>(nodes);
37 }
38
39 /**
40 * Set new list of nodes to way. This method is preferred to multiple calls to addNode/removeNode
41 * and similar methods because nodes are internally saved as array which means lower memory overhead
42 * but also slower modifying operations.
43 * @param nodes New way nodes. Can be null, in that case all way nodes are removed
44 * @since 1862
45 */
46 public void setNodes(List<Node> nodes) {
47 if (nodes == null) {
48 this.nodes = new Node[0];
49 } else {
50 this.nodes = nodes.toArray(new Node[nodes.size()]);
51 }
52 clearCached();
53 }
54
55 /**
56 * Replies the number of nodes in this ways.
57 *
58 * @return the number of nodes in this ways.
59 * @since 1862
60 */
61 public int getNodesCount() {
62 return nodes.length;
63 }
64
65 /**
66 * Replies the node at position <code>index</code>.
67 *
68 * @param index the position
69 * @return the node at position <code>index</code>
70 * @exception IndexOutOfBoundsException thrown if <code>index</code> < 0
71 * or <code>index</code> >= {@see #getNodesCount()}
72 * @since 1862
73 */
74 public Node getNode(int index) {
75 return nodes[index];
76 }
77
78 /**
79 * Replies true if this way contains the node <code>node</code>, false
80 * otherwise. Replies false if <code>node</code> is null.
81 *
82 * @param node the node. May be null.
83 * @return true if this way contains the node <code>node</code>, false
84 * otherwise
85 * @since 1909
86 */
87 public boolean containsNode(Node node) {
88 if (node == null) return false;
89 for (int i=0; i<nodes.length; i++) {
90 if (nodes[i].equals(node))
91 return true;
92 }
93 return false;
94 }
95
96 /* mappaint data */
97 public boolean isMappaintArea = false;
98 public Integer mappaintDrawnAreaCode = 0;
99 /* end of mappaint data */
100 @Override protected void clearCached() {
101 super.clearCached();
102 isMappaintArea = false;
103 mappaintDrawnAreaCode = 0;
104 }
105
106 public ArrayList<Pair<Node,Node>> getNodePairs(boolean sort) {
107 ArrayList<Pair<Node,Node>> chunkSet = new ArrayList<Pair<Node,Node>>();
108 if (incomplete) return chunkSet;
109 Node lastN = null;
110 for (Node n : this.nodes) {
111 if (lastN == null) {
112 lastN = n;
113 continue;
114 }
115 Pair<Node,Node> np = new Pair<Node,Node>(lastN, n);
116 if (sort) {
117 Pair.sort(np);
118 }
119 chunkSet.add(np);
120 lastN = n;
121 }
122 return chunkSet;
123 }
124
125
126 @Override public void visit(Visitor visitor) {
127 visitor.visit(this);
128 }
129
130 /**
131 * Creates a new way with id 0.
132 *
133 */
134 public Way(){
135 super(0);
136 }
137
138 /**
139 * Create an identical clone of the argument (including the id).
140 *
141 * @param original the original way. Must not be null.
142 */
143 public Way(Way original) {
144 super(original.getId());
145 cloneFrom(original);
146 }
147
148 /**
149 * Creates a new way for the given id. If the id > 0, the way is marked
150 * as incomplete.
151 *
152 * @param id the id. > 0 required
153 * @throws IllegalArgumentException thrown if id < 0
154 */
155 public Way(long id) throws IllegalArgumentException {
156 super(id);
157 }
158
159 @Override public void cloneFrom(OsmPrimitive osm) {
160 super.cloneFrom(osm);
161 Way otherWay = (Way)osm;
162 nodes = new Node[otherWay.nodes.length];
163 System.arraycopy(otherWay.nodes, 0, nodes, 0, otherWay.nodes.length);
164 }
165
166 @Override public String toString() {
167 if (incomplete) return "{Way id="+getId()+" version="+getVersion()+" (incomplete)}";
168 return "{Way id="+getId()+" version="+getVersion()+" nodes="+Arrays.toString(nodes)+"}";
169 }
170
171 @Override
172 public boolean hasEqualSemanticAttributes(OsmPrimitive other) {
173 if (other == null || ! (other instanceof Way) )
174 return false;
175 if (! super.hasEqualSemanticAttributes(other))
176 return false;
177 Way w = (Way)other;
178 return Arrays.equals(nodes, w.nodes);
179 }
180
181 public int compareTo(OsmPrimitive o) {
182 if (o instanceof Relation)
183 return 1;
184 return o instanceof Way ? Long.valueOf(getId()).compareTo(o.getId()) : -1;
185 }
186
187 public void removeNode(Node n) {
188 if (incomplete) return;
189 boolean closed = (lastNode() == n && firstNode() == n);
190 int i;
191 List<Node> copy = getNodes();
192 while ((i = copy.indexOf(n)) >= 0) {
193 copy.remove(i);
194 }
195 i = copy.size();
196 if (closed && i > 2) {
197 addNode(firstNode());
198 } else if (i >= 2 && i <= 3 && copy.get(0) == copy.get(i-1)) {
199 copy.remove(i-1);
200 }
201 setNodes(copy);
202 }
203
204 public void removeNodes(Collection<? extends OsmPrimitive> selection) {
205 if (incomplete) return;
206 for(OsmPrimitive p : selection) {
207 if (p instanceof Node) {
208 removeNode((Node)p);
209 }
210 }
211 }
212
213 /**
214 * Adds a node to the end of the list of nodes. Ignored, if n is null.
215 *
216 * @param n the node. Ignored, if null.
217 * @throws IllegalStateException thrown, if this way is marked as incomplete. We can't add a node
218 * to an incomplete way
219 */
220 public void addNode(Node n) throws IllegalStateException {
221 if (n==null) return;
222 if (incomplete)
223 throw new IllegalStateException(tr("Cannot add node {0} to incomplete way {1}.", n.getId(), getId()));
224 clearCached();
225 Node[] newNodes = new Node[nodes.length + 1];
226 System.arraycopy(nodes, 0, newNodes, 0, nodes.length);
227 newNodes[nodes.length] = n;
228 nodes = newNodes;
229 }
230
231 /**
232 * Adds a node at position offs.
233 *
234 * @param int offs the offset
235 * @param n the node. Ignored, if null.
236 * @throws IllegalStateException thrown, if this way is marked as incomplete. We can't add a node
237 * to an incomplete way
238 * @throws IndexOutOfBoundsException thrown if offs is out of bounds
239 */
240 public void addNode(int offs, Node n) throws IllegalStateException, IndexOutOfBoundsException {
241 if (n==null) return;
242 if (incomplete)
243 throw new IllegalStateException(tr("Cannot add node {0} to incomplete way {1}.", n.getId(), getId()));
244 clearCached();
245 Node[] newNodes = new Node[nodes.length + 1];
246 System.arraycopy(nodes, 0, newNodes, 0, offs);
247 System.arraycopy(nodes, offs, newNodes, offs + 1, nodes.length - offs);
248 newNodes[offs] = n;
249 nodes = newNodes;
250 }
251
252 public boolean isClosed() {
253 if (incomplete) return false;
254 return nodes.length >= 3 && lastNode() == firstNode();
255 }
256
257 public Node lastNode() {
258 if (incomplete || nodes.length == 0) return null;
259 return nodes[nodes.length-1];
260 }
261
262 public Node firstNode() {
263 if (incomplete || nodes.length == 0) return null;
264 return nodes[0];
265 }
266
267 public boolean isFirstLastNode(Node n) {
268 if (incomplete || nodes.length == 0) return false;
269 return n == firstNode() || n == lastNode();
270 }
271
272 @Override
273 public String getDisplayName(NameFormatter formatter) {
274 return formatter.format(this);
275 }
276}
Note: See TracBrowser for help on using the repository browser.