Changeset 26837 in osm
- Timestamp:
- 2011-10-12T09:22:23+02:00 (13 years ago)
- Location:
- applications/editors/josm/plugins/reltoolbox/src/relcontext
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/reltoolbox/src/relcontext/RelContextDialog.java
r26290 r26837 516 516 addMenuItem("tags", tr("Move area tags from contour to relation")); 517 517 addMenuItem("alltags", tr("When moving tags, consider even non-repeating ones")); 518 addMenuItem("allowsplit", tr("Allow splitting of ways in neighbouring multipolygons")); 518 519 } 519 520 -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/CreateMultipolygonAction.java
r26834 r26837 12 12 import org.openstreetmap.josm.actions.JosmAction; 13 13 import org.openstreetmap.josm.command.*; 14 import org.openstreetmap.josm.data.coor.EastNorth;15 14 import org.openstreetmap.josm.data.osm.*; 16 import org.openstreetmap.josm.gui.DefaultNameFormatter;17 15 import org.openstreetmap.josm.tools.GBC; 18 import org.openstreetmap.josm.tools.Geometry;19 import org.openstreetmap.josm.tools.Geometry.PolygonIntersection;20 16 import org.openstreetmap.josm.tools.Shortcut; 21 17 import relcontext.ChosenRelation; … … 55 51 else if( property.equals("single") ) 56 52 return true; 53 else if( property.equals("allowsplit") ) 54 return false; 57 55 throw new IllegalArgumentException(property); 58 56 } … … 66 64 Collection<Way> selectedWays = getCurrentDataSet().getSelectedWays(); 67 65 if( !isBoundary && getPref("tags") ) { 68 if( selectedWays.size() == 1 && !selectedWays.iterator().next().isClosed() ) {69 Relation newRelation = tryToCloseOneWay(selectedWays.iterator().next());70 if( newRelation != null) {71 if( chRel != null)72 chRel.set(newRelation);73 getCurrentDataSet().setSelected(newRelation);74 return;75 }76 } 77 if( areAllOfThoseRings(getCurrentDataSet().getSelectedWays()) ) {78 List<Relation> rels = makeManySimpleMultipolygons(getCurrentDataSet().getSelectedWays());66 List<Command> commands = new ArrayList<Command>(); 67 List<Relation> rels = null; 68 if( getPref("allowsplit")) { 69 if( SplittingMultipolygons.canProcess(selectedWays) ) 70 rels = SplittingMultipolygons.process(getCurrentDataSet().getSelectedWays(), commands); 71 } else { 72 if( TheRing.areAllOfThoseRings(selectedWays) ) 73 rels = TheRing.makeManySimpleMultipolygons(getCurrentDataSet().getSelectedWays(), commands); 74 } 75 if( !commands.isEmpty() && rels != null && !rels.isEmpty() ) { 76 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygons from rings"), commands)); 79 77 if( chRel != null ) 80 78 chRel.set(rels.size() == 1 ? rels.get(0) : null); … … 405 403 return true; 406 404 } 407 408 private boolean areAllOfThoseRings( Collection<Way> ways ) {409 List<Way> rings = new ArrayList<Way>();410 for( Way way : ways ) {411 if( way.isClosed() )412 rings.add(way);413 else414 return false;415 }416 if( rings.isEmpty() || ways.size() == 1 )417 return false; // todo: for one ring, attach it to neares multipolygons418 419 // check for non-containment of rings420 for( int i = 0; i < rings.size() - 1; i++ ) {421 for( int j = i + 1; j < rings.size(); j++ ) {422 PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes());423 if( intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST )424 return false;425 }426 }427 428 return true;429 }430 431 /**432 * Creates ALOT of Multipolygons and pets him gently.433 * @return list of new relations.434 */435 private List<Relation> makeManySimpleMultipolygons( Collection<Way> selection ) {436 System.out.println("---------------------------------------");437 List<TheRing> rings = new ArrayList<TheRing>(selection.size());438 for( Way w : selection )439 rings.add(new TheRing(w));440 for( int i = 0; i < rings.size()-1; i++ )441 for( int j = i+1; j < rings.size(); j++ )442 rings.get(i).collide(rings.get(j));443 TheRing.redistributeSegments(rings);444 List<Command> commands = new ArrayList<Command>();445 List<Relation> relations = new ArrayList<Relation>();446 for( TheRing r : rings ) {447 commands.addAll(r.getCommands());448 relations.add(r.getRelation());449 }450 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygons from rings"), commands));451 return relations;452 }453 454 /**455 * Appends "append" to "base" so the closed polygon forms.456 */457 private static void closePolygon( List<Node> base, List<Node> append ) {458 if( append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1)) ) {459 List<Node> ap2 = new ArrayList<Node>(append);460 Collections.reverse(ap2);461 append = ap2;462 }463 base.remove(base.size() - 1);464 base.addAll(append);465 }466 467 /**468 * Checks if a middle point between two nodes is inside a polygon. Useful to check if the way is inside.469 */470 private static boolean segmentInsidePolygon( Node n1, Node n2, List<Node> polygon ) {471 EastNorth en1 = n1.getEastNorth();472 EastNorth en2 = n2.getEastNorth();473 Node testNode = new Node(new EastNorth((en1.east() + en2.east()) / 2.0, (en1.north() + en2.north()) / 2.0));474 return Geometry.nodeInsidePolygon(testNode, polygon);475 }476 477 /**478 * Splits a way with regard to containing relations. This modifies the way and the relation, be prepared.479 * @param w The way.480 * @param n The node to split at.481 * @param commands List of commands to add way/relation changing to. If null, never mind.482 * @return Newly created ways. <b>Warning:</b> if commands is no not, newWays contains {@code w}.483 */484 public static List<Way> splitWay( Way w, Node n1, Node n2, List<Command> commands ) {485 List<Node> nodes = new ArrayList<Node>(w.getNodes());486 if( w.isClosed())487 nodes.remove(nodes.size()-1);488 int index1 = nodes.indexOf(n1);489 int index2 = n2 == null ? -1 : nodes.indexOf(n2);490 if( index1 > index2 ) {491 int tmp = index1;492 index1 = index2;493 index2 = tmp;494 }495 // right now index2 >= index1496 if( index2 < 1 || index1 >= w.getNodesCount() - 1 || index2 >= w.getNodesCount() )497 return Collections.emptyList();498 if( w.isClosed() && (index1 < 0 || index1 == index2 || index1 + w.getNodesCount() == index2) )499 return Collections.emptyList();500 501 // make a list of segments502 List<List<Node>> chunks = new ArrayList<List<Node>>(2);503 List<Node> chunk = new ArrayList<Node>();504 for( int i = 0; i < nodes.size(); i++ ) {505 chunk.add(nodes.get(i));506 if( (w.isClosed() || chunk.size() > 1) && (i == index1 || i == index2) ) {507 chunks.add(chunk);508 chunk = new ArrayList<Node>();509 chunk.add(nodes.get(i));510 }511 }512 chunks.add(chunk);513 514 // for closed way ignore the way boundary515 if( w.isClosed() ) {516 chunks.get(chunks.size() - 1).addAll(chunks.get(0));517 chunks.remove(0);518 } else if( chunks.get(chunks.size()-1).size() < 2 )519 chunks.remove(chunks.size()-1);520 521 // todo remove debug: show chunks array contents522 /*for( List<Node> c1 : chunks ) {523 for( Node cn1 : c1 )524 System.out.print(cn1.getId() + ",");525 System.out.println();526 }*/527 528 // build a map of referencing relations529 Map<Relation, Integer> references = new HashMap<Relation, Integer>();530 List<Command> relationCommands = new ArrayList<Command>();531 for( OsmPrimitive p : w.getReferrers() ) {532 if( p instanceof Relation ) {533 Relation rel = commands == null ? (Relation)p : new Relation((Relation)p);534 if( commands != null )535 relationCommands.add(new ChangeCommand((Relation)p, rel));536 for( int i = 0; i < rel.getMembersCount(); i++ )537 if( rel.getMember(i).getMember().equals(w) )538 references.put(rel, Integer.valueOf(i));539 }540 }541 542 // build ways543 List<Way> result = new ArrayList<Way>();544 Way updatedWay = commands == null ? w : new Way(w);545 updatedWay.setNodes(chunks.get(0));546 if( commands != null ) {547 commands.add(new ChangeCommand(w, updatedWay));548 result.add(updatedWay);549 }550 551 for( int i = 1; i < chunks.size(); i++ ) {552 List<Node> achunk = chunks.get(i);553 Way newWay = new Way();554 newWay.setKeys(w.getKeys());555 result.add(newWay);556 for( Relation rel : references.keySet() ) {557 int relIndex = references.get(rel);558 rel.addMember(relIndex + 1, new RelationMember(rel.getMember(relIndex).getRole(), newWay));559 }560 newWay.setNodes(achunk);561 if( commands != null )562 commands.add(new AddCommand(newWay));563 }564 if( commands != null )565 commands.addAll(relationCommands);566 return result;567 }568 569 public static List<Way> splitWay( Way w, Node n1, Node n2 ) {570 return splitWay(w, n1, n2, null);571 }572 573 /**574 * Find a way the tips of a segment, ensure it's in a multipolygon and try to close the relation.575 */576 private Relation tryToCloseOneWay( Way segment ) {577 if( segment.isClosed() || segment.isIncomplete() )578 return null;579 580 List<Way> ways = intersection(581 OsmPrimitive.getFilteredList(segment.firstNode().getReferrers(), Way.class),582 OsmPrimitive.getFilteredList(segment.lastNode().getReferrers(), Way.class));583 ways.remove(segment);584 for( Iterator<Way> iter = ways.iterator(); iter.hasNext(); ) {585 boolean save = false;586 for( OsmPrimitive ref : iter.next().getReferrers() )587 if( ref instanceof Relation && ((Relation)ref).isMultipolygon() && !ref.isDeleted() )588 save = true;589 if( !save )590 iter.remove();591 }592 if( ways.isEmpty() )593 return null; // well...594 Way target = ways.get(0);595 596 // time to create a new multipolygon relation and a command stack597 List<Command> commands = new ArrayList<Command>();598 Relation newRelation = new Relation();599 newRelation.put("type", "multipolygon");600 newRelation.addMember(new RelationMember("outer", segment));601 Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", DEFAULT_LINEAR_TAGS);602 Way segmentCopy = new Way(segment);603 boolean changed = false;604 for( String key : segmentCopy.keySet() ) {605 if( !linearTags.contains(key) ) {606 newRelation.put(key, segmentCopy.get(key));607 segmentCopy.remove(key);608 changed = true;609 }610 }611 if( changed )612 commands.add(new ChangeCommand(segment, segmentCopy));613 614 // now split the way, at last615 List<Way> newWays = new ArrayList<Way>(splitWay(target, segment.firstNode(), segment.lastNode(), commands));616 617 Way addingWay = null;618 if( target.isClosed() ) {619 Way utarget = newWays.get(1);620 Way alternate = newWays.get(0);621 List<Node> testRing = new ArrayList<Node>(segment.getNodes());622 closePolygon(testRing, utarget.getNodes());623 addingWay = segmentInsidePolygon(alternate.getNode(0), alternate.getNode(1), testRing) ? alternate : utarget;624 } else {625 for( Way w : newWays ) {626 if( (w.firstNode().equals(segment.firstNode()) && w.lastNode().equals(segment.lastNode()))627 || (w.firstNode().equals(segment.lastNode()) && w.lastNode().equals(segment.firstNode())) ) {628 addingWay = w;629 break;630 }631 }632 }633 newRelation.addMember(new RelationMember("outer", addingWay.getUniqueId() == target.getUniqueId() ? target : addingWay));634 commands.add(new AddCommand(newRelation));635 Main.main.undoRedo.add(new SequenceCommand(tr("Complete multipolygon for way {0}",636 DefaultNameFormatter.getInstance().format(segment)), commands));637 return newRelation;638 }639 640 /**641 * Returns all elements from {@code list1} that are in {@code list2}.642 */643 private static <T> List<T> intersection( Collection<T> list1, Collection<T> list2 ) {644 List<T> result = new ArrayList<T>();645 for( T item : list1 )646 if( list2.contains(item) )647 result.add(item);648 return result;649 }650 405 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/TheRing.java
r26834 r26837 8 8 import org.openstreetmap.josm.data.osm.*; 9 9 import org.openstreetmap.josm.tools.Geometry; 10 import org.openstreetmap.josm.tools.Geometry.PolygonIntersection; 10 11 11 12 /** … … 28 29 } 29 30 31 public static boolean areAllOfThoseRings( Collection<Way> ways ) { 32 List<Way> rings = new ArrayList<Way>(); 33 for( Way way : ways ) { 34 if( way.isClosed() ) 35 rings.add(way); 36 else 37 return false; 38 } 39 if( rings.isEmpty() || ways.size() == 1 ) 40 return false; 41 42 // check for non-containment of rings 43 for( int i = 0; i < rings.size() - 1; i++ ) { 44 for( int j = i + 1; j < rings.size(); j++ ) { 45 PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes()); 46 if( intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST ) 47 return false; 48 } 49 } 50 51 return true; 52 } 53 54 /** 55 * Creates ALOT of Multipolygons and pets him gently. 56 * @return list of new relations. 57 */ 58 public static List<Relation> makeManySimpleMultipolygons( Collection<Way> selection, List<Command> commands ) { 59 System.out.println("---------------------------------------"); 60 List<TheRing> rings = new ArrayList<TheRing>(selection.size()); 61 for( Way w : selection ) 62 rings.add(new TheRing(w)); 63 for( int i = 0; i < rings.size() - 1; i++ ) 64 for( int j = i + 1; j < rings.size(); j++ ) 65 rings.get(i).collide(rings.get(j)); 66 redistributeSegments(rings); 67 List<Relation> relations = new ArrayList<Relation>(); 68 for( TheRing r : rings ) { 69 commands.addAll(r.getCommands()); 70 relations.add(r.getRelation()); 71 } 72 return relations; 73 } 74 30 75 public void collide( TheRing other ) { 31 76 boolean collideNoted = false;
Note:
See TracChangeset
for help on using the changeset viewer.