source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java@ 2494

Last change on this file since 2494 was 2494, checked in by Gubaer, 16 years ago

Code related to #3999. Uncommented for the time being.

  • Property svn:eol-style set to native
File size: 27.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.BACKWARD;
5import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.FORWARD;
6import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.NONE;
7import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.ROUNDABOUT_LEFT;
8import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.ROUNDABOUT_RIGHT;
9
10import java.util.ArrayList;
11import java.util.Arrays;
12import java.util.Collection;
13import java.util.Collections;
14import java.util.HashSet;
15import java.util.Iterator;
16import java.util.LinkedList;
17import java.util.List;
18import java.util.Set;
19import java.util.concurrent.CopyOnWriteArrayList;
20
21import javax.swing.DefaultListSelectionModel;
22import javax.swing.ListSelectionModel;
23import javax.swing.event.TableModelEvent;
24import javax.swing.event.TableModelListener;
25import javax.swing.table.AbstractTableModel;
26
27import org.openstreetmap.josm.Main;
28import org.openstreetmap.josm.data.coor.EastNorth;
29import org.openstreetmap.josm.data.osm.Node;
30import org.openstreetmap.josm.data.osm.OsmPrimitive;
31import org.openstreetmap.josm.data.osm.Relation;
32import org.openstreetmap.josm.data.osm.RelationMember;
33import org.openstreetmap.josm.data.osm.Way;
34import org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction;
35import org.openstreetmap.josm.gui.layer.OsmDataLayer;
36
37public class MemberTableModel extends AbstractTableModel implements TableModelListener {
38
39 /**
40 * data of the table model: The list of members and the cached WayConnectionType of each member.
41 **/
42 private ArrayList<RelationMember> members;
43 private ArrayList<WayConnectionType> connectionType = null;
44
45 private DefaultListSelectionModel listSelectionModel;
46 private CopyOnWriteArrayList<IMemberModelListener> listeners;
47 private OsmDataLayer layer;
48
49 /**
50 * constructor
51 */
52 public MemberTableModel(OsmDataLayer layer) {
53 members = new ArrayList<RelationMember>();
54 listeners = new CopyOnWriteArrayList<IMemberModelListener>();
55 this.layer = layer;
56 addTableModelListener(this);
57 }
58
59 public void addMemberModelListener(IMemberModelListener listener) {
60 synchronized (listeners) {
61 if (listener != null && !listeners.contains(listener)) {
62 listeners.add(listener);
63 }
64 }
65 }
66
67 public void removeMemberModelListener(IMemberModelListener listener) {
68 synchronized (listeners) {
69 if (listener != null && listeners.contains(listener)) {
70 listeners.remove(listener);
71 }
72 }
73 }
74
75 protected void fireMakeMemberVisible(int index) {
76 synchronized (listeners) {
77 for (IMemberModelListener listener : listeners) {
78 listener.makeMemberVisible(index);
79 }
80 }
81 }
82
83 public void populate(Relation relation) {
84 members.clear();
85 if (relation != null) {
86 // make sure we work with clones of the relation members
87 // in the model.
88 members.addAll(new Relation(relation).getMembers());
89 }
90 fireTableDataChanged();
91 }
92
93 public int getColumnCount() {
94 return 3;
95 }
96
97 public int getRowCount() {
98 return members.size();
99 }
100
101 public Object getValueAt(int rowIndex, int columnIndex) {
102 switch (columnIndex) {
103 case 0:
104 return members.get(rowIndex).getRole();
105 case 1:
106 return members.get(rowIndex).getMember();
107 case 2:
108 return wayConnection(rowIndex);
109 }
110 // should not happen
111 return null;
112 }
113
114 @Override
115 public boolean isCellEditable(int rowIndex, int columnIndex) {
116 return columnIndex == 0;
117 }
118
119 @Override
120 public void setValueAt(Object value, int rowIndex, int columnIndex) {
121 RelationMember member = members.get(rowIndex);
122 RelationMember newMember = new RelationMember(value.toString(), member.getMember());
123 members.remove(rowIndex);
124 members.add(rowIndex, newMember);
125 }
126
127 public OsmPrimitive getReferredPrimitive(int idx) {
128 return members.get(idx).getMember();
129 }
130
131 public void moveUp(int[] selectedRows) {
132 if (!canMoveUp(selectedRows))
133 return;
134
135 for (int row : selectedRows) {
136 RelationMember member1 = members.get(row);
137 RelationMember member2 = members.get(row - 1);
138 members.set(row, member2);
139 members.set(row - 1, member1);
140 }
141 fireTableDataChanged();
142 getSelectionModel().setValueIsAdjusting(true);
143 getSelectionModel().clearSelection();
144 for (int row : selectedRows) {
145 row--;
146 getSelectionModel().addSelectionInterval(row, row);
147 }
148 getSelectionModel().setValueIsAdjusting(false);
149 fireMakeMemberVisible(selectedRows[0] - 1);
150 }
151
152 public void moveDown(int[] selectedRows) {
153 if (!canMoveDown(selectedRows))
154 return;
155
156 for (int i = selectedRows.length - 1; i >= 0; i--) {
157 int row = selectedRows[i];
158 RelationMember member1 = members.get(row);
159 RelationMember member2 = members.get(row + 1);
160 members.set(row, member2);
161 members.set(row + 1, member1);
162 }
163 fireTableDataChanged();
164 getSelectionModel();
165 getSelectionModel().setValueIsAdjusting(true);
166 getSelectionModel().clearSelection();
167 for (int row : selectedRows) {
168 row++;
169 getSelectionModel().addSelectionInterval(row, row);
170 }
171 getSelectionModel().setValueIsAdjusting(false);
172 fireMakeMemberVisible(selectedRows[0] + 1);
173 }
174
175 public void remove(int[] selectedRows) {
176 if (!canRemove(selectedRows))
177 return;
178 int offset = 0;
179 for (int row : selectedRows) {
180 row -= offset;
181 members.remove(row);
182 offset++;
183 }
184 fireTableDataChanged();
185 }
186
187 public boolean canMoveUp(int[] rows) {
188 if (rows == null || rows.length == 0)
189 return false;
190 Arrays.sort(rows);
191 return rows[0] > 0 && members.size() > 0;
192 }
193
194 public boolean canMoveDown(int[] rows) {
195 if (rows == null || rows.length == 0)
196 return false;
197 Arrays.sort(rows);
198 return members.size() > 0 && rows[rows.length - 1] < members.size() - 1;
199 }
200
201 public boolean canRemove(int[] rows) {
202 if (rows == null || rows.length == 0)
203 return false;
204 return true;
205 }
206
207 public DefaultListSelectionModel getSelectionModel() {
208 if (listSelectionModel == null) {
209 listSelectionModel = new DefaultListSelectionModel();
210 listSelectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
211 }
212 return listSelectionModel;
213 }
214
215 public void removeMembersReferringTo(List<? extends OsmPrimitive> primitives) {
216 if (primitives == null)
217 return;
218 Iterator<RelationMember> it = members.iterator();
219 while (it.hasNext()) {
220 RelationMember member = it.next();
221 if (primitives.contains(member.getMember())) {
222 it.remove();
223 }
224 }
225 fireTableDataChanged();
226 }
227
228 public void applyToRelation(Relation relation) {
229 relation.setMembers(members);
230 }
231
232 public boolean hasSameMembersAs(Relation relation) {
233 if (relation == null)
234 return false;
235 if (relation.getMembersCount() != members.size())
236 return false;
237 for (int i = 0; i < relation.getMembersCount(); i++) {
238 if (!relation.getMember(i).equals(members.get(i)))
239 return false;
240 }
241 return true;
242 }
243
244 public boolean hasIncompleteMembers() {
245 for (RelationMember member : members) {
246 if (member.getMember().incomplete)
247 return true;
248 }
249 return false;
250 }
251
252 protected List<Integer> getSelectedIndices() {
253 ArrayList<Integer> selectedIndices = new ArrayList<Integer>();
254 for (int i = 0; i < members.size(); i++) {
255 if (getSelectionModel().isSelectedIndex(i)) {
256 selectedIndices.add(i);
257 }
258 }
259 return selectedIndices;
260 }
261
262 public void addMembersAtBeginning(List<OsmPrimitive> primitives) {
263 if (primitives == null)
264 return;
265 for (OsmPrimitive primitive : primitives) {
266 RelationMember member = new RelationMember("", primitive);
267 members.add(0, member);
268 }
269 fireTableDataChanged();
270 getSelectionModel().clearSelection();
271 for (int i = 0; i < primitives.size(); i++) {
272 getSelectionModel().addSelectionInterval(i, i);
273 }
274 fireMakeMemberVisible(0);
275 }
276
277 public void addMembersAtEnd(List<? extends OsmPrimitive> primitives) {
278 if (primitives == null)
279 return;
280
281 for (OsmPrimitive primitive : primitives) {
282 RelationMember member = new RelationMember("", primitive);
283 members.add(member);
284 }
285 fireTableDataChanged();
286 getSelectionModel().clearSelection();
287 for (int i = 0; i < primitives.size(); i++) {
288 getSelectionModel().addSelectionInterval(members.size() - 1 - i, members.size() - 1 - i);
289 }
290 fireMakeMemberVisible(members.size() - 1);
291 }
292
293 public void addMembersBeforeIdx(List<? extends OsmPrimitive> primitives, int idx) {
294 if (primitives == null)
295 return;
296
297 for (OsmPrimitive primitive : primitives) {
298 RelationMember member = new RelationMember("", primitive);
299 members.add(idx, member);
300 }
301 fireTableDataChanged();
302 getSelectionModel().setValueIsAdjusting(true);
303 getSelectionModel().clearSelection();
304 for (int i = 0; i < primitives.size(); i++) {
305 getSelectionModel().addSelectionInterval(idx + i, idx + i);
306 }
307 getSelectionModel().setValueIsAdjusting(false);
308 fireMakeMemberVisible(idx);
309 }
310
311 public void addMembersAfterIdx(List<? extends OsmPrimitive> primitives, int idx) {
312 if (primitives == null)
313 return;
314 int j = 1;
315 for (OsmPrimitive primitive : primitives) {
316 RelationMember member = new RelationMember("", primitive);
317 members.add(idx + j, member);
318 j++;
319 }
320 fireTableDataChanged();
321 getSelectionModel().setValueIsAdjusting(true);
322 getSelectionModel().clearSelection();
323 for (int i = 0; i < primitives.size(); i++) {
324 getSelectionModel().addSelectionInterval(idx + 1 + i, idx + 1 + i);
325 }
326 getSelectionModel().setValueIsAdjusting(false);
327 fireMakeMemberVisible(idx + 1);
328 }
329
330 /**
331 * Replies the number of members which refer to a particular primitive
332 *
333 * @param primitive the primitive
334 * @return the number of members which refer to a particular primitive
335 */
336 public int getNumMembersWithPrimitive(OsmPrimitive primitive) {
337 int count = 0;
338 for (RelationMember member : members) {
339 if (member.getMember().equals(primitive)) {
340 count++;
341 }
342 }
343 return count;
344 }
345
346 /**
347 * updates the role of the members given by the indices in <code>idx</code>
348 *
349 * @param idx the array of indices
350 * @param role the new role
351 */
352 public void updateRole(int[] idx, String role) {
353 if (idx == null || idx.length == 0)
354 return;
355 for (int row : idx) {
356 RelationMember oldMember = members.get(row);
357 RelationMember newMember = new RelationMember(role, oldMember.getMember());
358 members.remove(row);
359 members.add(row, newMember);
360 }
361 fireTableDataChanged();
362 for (int row : idx) {
363 getSelectionModel().addSelectionInterval(row, row);
364 }
365 }
366
367 /**
368 * Get the currently selected relation members
369 *
370 * @return a collection with the currently selected relation members
371 */
372 public Collection<RelationMember> getSelectedMembers() {
373 ArrayList<RelationMember> selectedMembers = new ArrayList<RelationMember>();
374 for (int i : getSelectedIndices()) {
375 selectedMembers.add(members.get(i));
376 }
377 return selectedMembers;
378 }
379
380 /**
381 * Replies the set of selected referers. Never null, but may be empty.
382 *
383 * @return the set of selected referers
384 */
385 public Set<OsmPrimitive> getSelectedChildPrimitives() {
386 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
387 for (RelationMember m: getSelectedMembers()) {
388 ret.add(m.getMember());
389 }
390 return ret;
391 }
392
393 /**
394 * Replies the set of selected referers. Never null, but may be empty.
395 *
396 * @return the set of selected referers
397 */
398 public Set<OsmPrimitive> getChildPrimitives(Collection<? extends OsmPrimitive> referenceSet) {
399 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
400 if (referenceSet == null) return null;
401 for (RelationMember m: members) {
402 if (referenceSet.contains(m.getMember())) {
403 ret.add(m.getMember());
404 }
405 }
406 return ret;
407 }
408
409
410 /**
411 * Replies true, if the selected {@see OsmPrimitive}s in the layer belonging
412 * to this model are in sync with the selected referers in this model.
413 *
414 * @return
415 */
416 public boolean selectionsAreInSync() {
417 HashSet<OsmPrimitive> s1 = new HashSet<OsmPrimitive>(getSelectedChildPrimitives());
418 if (s1.size() != layer.data.getSelected().size()) return false;
419 s1.removeAll(layer.data.getSelected());
420 return s1.isEmpty();
421 }
422 /**
423 * Selects the members in the collection selectedMembers
424 *
425 * @param selectedMembers the collection of selected members
426 */
427 public void setSelectedMembers(Collection<RelationMember> selectedMembers) {
428 if (selectedMembers == null || selectedMembers.isEmpty())
429 return;
430
431 // lookup the indices for the respective members
432 //
433 ArrayList<Integer> selectedIndices = new ArrayList<Integer>();
434 for (RelationMember member : selectedMembers) {
435 for (int idx = 0; idx < members.size(); idx ++) {
436 if (members.get(idx).equals(member)) {
437 if (!selectedIndices.contains(idx)) {
438 selectedIndices.add(idx);
439 }
440 }
441 }
442 }
443
444 // select the members
445 //
446 Collections.sort(selectedIndices);
447 getSelectionModel().setValueIsAdjusting(true);
448 getSelectionModel().clearSelection();
449 for (int row : selectedIndices) {
450 getSelectionModel().addSelectionInterval(row, row);
451 }
452 getSelectionModel().setValueIsAdjusting(false);
453
454 // make the first selected member visible
455 //
456 if (selectedIndices.size() > 0) {
457 fireMakeMemberVisible(selectedIndices.get(0));
458 }
459 }
460
461 /**
462 * Replies true if the index-th relation members referrs
463 * to an editable relation, i.e. a relation which is not
464 * incomplete.
465 *
466 * @param index the index
467 * @return true, if the index-th relation members referrs
468 * to an editable relation, i.e. a relation which is not
469 * incomplete
470 */
471 public boolean isEditableRelation(int index) {
472 if (index < 0 || index >= members.size())
473 return false;
474 RelationMember member = members.get(index);
475 if (!member.isRelation())
476 return false;
477 Relation r = member.getRelation();
478 return !r.incomplete;
479 }
480
481 /**
482 * Replies true if there is at least one relation member in this model
483 * which refers to at least on the primitives in <code>primitives</code>.
484 *
485 * @param primitives the collection of primitives
486 * @return true if there is at least one relation member in this model
487 * which refers to at least on the primitives in <code>primitives</code>; false
488 * otherwise
489 */
490 public boolean hasMembersReferringTo(Collection<OsmPrimitive> primitives) {
491 if (primitives == null || primitives.isEmpty())
492 return false;
493 HashSet<OsmPrimitive> referrers = new HashSet<OsmPrimitive>();
494 for(RelationMember member : members) {
495 referrers.add(member.getMember());
496 }
497 Iterator<OsmPrimitive> it = primitives.iterator();
498 while(it.hasNext()) {
499 OsmPrimitive referred = it.next();
500 if (referrers.contains(referred))
501 return true;
502 }
503 return false;
504 }
505
506 /**
507 * Selects all mebers which refer to {@see OsmPrimitive}s in the collections
508 * <code>primitmives</code>. Does nothing is primitives is null.
509 *
510 * @param primitives the collection of primitives
511 */
512 public void selectMembersReferringTo(Collection<? extends OsmPrimitive> primitives) {
513 if (primitives == null) return;
514 getSelectionModel().setValueIsAdjusting(true);
515 getSelectionModel().clearSelection();
516 for (int i=0; i< members.size();i++) {
517 RelationMember m = members.get(i);
518 if (primitives.contains(m.getMember())) {
519 this.getSelectionModel().addSelectionInterval(i,i);
520 }
521 }
522 getSelectionModel().setValueIsAdjusting(false);
523 if (getSelectedIndices().size() > 0) {
524 fireMakeMemberVisible(getSelectedIndices().get(0));
525 }
526 }
527
528 /**
529 * Replies true if the layer this model belongs to is equal to the active
530 * layer
531 *
532 * @return true if the layer this model belongs to is equal to the active
533 * layer
534 */
535 protected boolean isActiveLayer() {
536 if (Main.map == null || Main.map.mapView == null) return false;
537 return Main.map.mapView.getActiveLayer() == layer;
538 }
539
540 /**
541 * get a node we can link against when sorting members
542 * @param element the element we want to link against
543 * @param linked_element already linked against element
544 * @return the unlinked node if element is a way, the node itself if element is a node, null otherwise
545 */
546 private static Node getUnusedNode(RelationMember element, RelationMember linked_element)
547 {
548 Node result = null;
549
550 if (element.isWay()) {
551 Way w = element.getWay();
552 if (linked_element.isWay()) {
553 Way x = linked_element.getWay();
554 if ((w.firstNode() == x.firstNode()) || (w.firstNode() == x.lastNode())) {
555 result = w.lastNode();
556 } else {
557 result = w.firstNode();
558 }
559 } else if (linked_element.isNode()) {
560 Node m = linked_element.getNode();
561 if (w.firstNode() == m) {
562 result = w.lastNode();
563 } else {
564 result = w.firstNode();
565 }
566 }
567 } else if (element.isNode()) {
568 Node n = element.getNode();
569 result = n;
570 }
571
572 return result;
573 }
574
575 /**
576 * Sort the relation members by the way they are linked.
577 */
578 void sort() {
579 RelationNodeMap map = new RelationNodeMap(members);
580
581 // List of groups of linked members
582 //
583 ArrayList<LinkedList<Integer>> allGroups = new ArrayList<LinkedList<Integer>>();
584
585 // current group of members that are linked among each other
586 // Two successive members are always linked i.e. have a common node.
587 //
588 LinkedList<Integer> group;
589
590 Integer first;
591 while ((first = map.pop()) != null) {
592 group = new LinkedList<Integer>();
593 group.add(first);
594
595 allGroups.add(group);
596
597 Integer next = first;
598 while ((next = map.popAdjacent(next)) != null) {
599 group.addLast(next);
600 }
601
602 // The first element need not be in front of the list.
603 // So the search goes in both directions
604 //
605 next = first;
606 while ((next = map.popAdjacent(next)) != null) {
607 group.addFirst(next);
608 }
609
610 }
611
612 group = new LinkedList<Integer>();
613 group.addAll(map.getNotSortableMembers());
614 allGroups.add(group);
615
616 ArrayList<RelationMember> newMembers = new ArrayList<RelationMember>();
617 for (LinkedList<Integer> tmpGroup : allGroups) {
618 for (Integer p : tmpGroup) {
619 newMembers.add(members.get(p));
620 }
621 }
622
623 if (members.size() != newMembers.size()) throw new AssertionError();
624
625 members.clear();
626 members.addAll(newMembers);
627 fireTableDataChanged();
628 }
629
630 /**
631 * Determines the direction of way k with respect to the way ref_i.
632 * The way ref_i is assumed to have the direction ref_direction and
633 * to be the predecessor of k.
634 *
635 * If both ways are not linked in any way, NONE is returned.
636 *
637 * Else the direction is given as follows:
638 * Let the relation be a route of oneway streets, and someone travels them in the given order.
639 * Direction is FORWARD for if it is legel and BACKWARD if it is illegal to do so for the given way.
640 *
641 **/
642 private Direction determineDirection(int ref_i,Direction ref_direction, int k) {
643 if (ref_i < 0 || k < 0 || ref_i >= members.size() || k >= members.size())
644 return NONE;
645 if (ref_direction == NONE)
646 return NONE;
647
648 RelationMember m_ref = members.get(ref_i);
649 RelationMember m = members.get(k);
650 Way way_ref = null;
651 Way way = null;
652
653 if (m_ref.isWay()) {
654 way_ref = m_ref.getWay();
655 }
656 if (m.isWay()) {
657 way = m.getWay();
658 }
659
660 if (way_ref == null || way == null)
661 return NONE;
662
663 /** the list of nodes the way k can dock to */
664 List<Node> refNodes= new ArrayList<Node>();
665
666 switch (ref_direction) {
667 case FORWARD:
668 refNodes.add(way_ref.lastNode());
669 break;
670 case BACKWARD:
671 refNodes.add(way_ref.firstNode());
672 break;
673 case ROUNDABOUT_LEFT:
674 case ROUNDABOUT_RIGHT:
675 refNodes = way_ref.getNodes();
676 break;
677 }
678
679 if (refNodes == null)
680 return NONE;
681
682 for (Node n : refNodes) {
683 if (n == null) {
684 continue;
685 }
686 if (roundaboutType(k) != NONE) {
687 for (Node nn : way.getNodes()) {
688 if (n == nn)
689 return roundaboutType(k);
690 }
691 } else {
692 if (n == way.firstNode())
693 return FORWARD;
694 if (n == way.lastNode())
695 return BACKWARD;
696 }
697 }
698 return NONE;
699 }
700
701 /**
702 * determine, if the way i is a roundabout and if yes, what type of roundabout
703 */
704 private Direction roundaboutType(int i) { //FIXME
705 RelationMember m = members.get(i);
706 if (m == null || !m.isWay()) return NONE;
707 Way w = m.getWay();
708 return roundaboutType(w);
709 }
710 static Direction roundaboutType(Way w) {
711 if (w != null &&
712 "roundabout".equals(w.get("junction")) &&
713 w.getNodesCount() < 200 &&
714 w.getNodesCount() > 2 &&
715 w.getNode(0) != null &&
716 w.getNode(1) != null &&
717 w.getNode(2) != null &&
718 w.firstNode() == w.lastNode()) {
719 /** do some simple determinant / cross pruduct test on the first 3 nodes
720 to see, if the roundabout goes clock wise or ccw */
721 EastNorth en1 = w.getNode(0).getEastNorth();
722 EastNorth en2 = w.getNode(1).getEastNorth();
723 EastNorth en3 = w.getNode(2).getEastNorth();
724 en1 = en1.sub(en2);
725 en2 = en2.sub(en3);
726 return en1.north() * en2.east() - en2.north() * en1.east() > 0 ? ROUNDABOUT_LEFT : ROUNDABOUT_RIGHT;
727 } else
728 return NONE;
729 }
730
731 private WayConnectionType wayConnection(int i) {
732 if (connectionType == null) {
733 updateLinks();
734 }
735 return connectionType.get(i);
736 }
737
738 public void tableChanged(TableModelEvent e) {
739 connectionType = null;
740 }
741
742 /**
743 * refresh the cache of member WayConnectionTypes
744 */
745 public void updateLinks() {
746 connectionType = null;
747 ArrayList<WayConnectionType> con = new ArrayList<WayConnectionType>();
748
749 for (int i=0; i<members.size(); ++i) {
750 con.add(null);
751 }
752
753 int firstGroupIdx=0;
754 boolean resetFirstGoupIdx=false;
755
756 for (int i=0; i<members.size(); ++i) {
757 if (resetFirstGoupIdx) {
758 firstGroupIdx = i;
759 resetFirstGoupIdx = false;
760 }
761
762 RelationMember m = members.get(i);
763 if (! m.isWay()) {
764 con.set(i, new WayConnectionType());
765 resetFirstGoupIdx = true;
766 continue;
767 }
768
769 Way w = m.getWay();
770 if (w == null || w.incomplete) {
771 con.set(i, new WayConnectionType());
772 resetFirstGoupIdx = true;
773 continue;
774 }
775
776 boolean linkPrev = (i != firstGroupIdx);
777 boolean linkNext;
778 Direction dir;
779 if (linkPrev) {
780 dir = determineDirection(i-1, con.get(i-1).direction, i);
781 linkNext = (determineDirection(i, dir, i+1) != NONE);
782 }
783 else {
784 if (roundaboutType(i) != NONE) {
785 dir = determineDirection(i, roundaboutType(i), i+1) != NONE ? roundaboutType(i) : NONE;
786 } else { /** guess the direction and see if it fits with the next member */
787 dir = determineDirection(i, FORWARD, i+1) != NONE ? FORWARD : NONE;
788 if (dir == NONE) {
789 dir = determineDirection(i, BACKWARD, i+1) != NONE ? BACKWARD : NONE;
790 }
791 }
792 linkNext = (dir != NONE);
793 if (dir == NONE) {
794 if (roundaboutType(i) != NONE) {
795 dir = roundaboutType(i);
796 }
797 }
798
799 }
800
801 con.set(i, new WayConnectionType(linkPrev, linkNext, dir));
802
803 if (! linkNext) {
804 boolean loop;
805 if (i == firstGroupIdx) {
806 loop = determineDirection(i, FORWARD, i) == FORWARD;
807 } else {
808 loop = determineDirection(i, dir, firstGroupIdx) == con.get(firstGroupIdx).direction;
809 }
810 if (loop) {
811 for (int j=firstGroupIdx; j <= i; ++j) {
812 con.get(j).isLoop = true;
813 }
814 }
815 resetFirstGoupIdx = true;
816 }
817 }
818 connectionType = con;
819 // for (int i=0; i<con.size(); ++i) {
820 // System.err.println(con.get(i));
821 // }
822 }
823}
Note: See TracBrowser for help on using the repository browser.