Ignore:
Timestamp:
2011-10-09T20:55:07+02:00 (13 years ago)
Author:
zverik
Message:

almost works

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/CreateMultipolygonAction.java

    r26812 r26815  
    459459            for( int j = i+1; j < rings.size(); j++ )
    460460                rings.get(i).collide(rings.get(j));
    461         redistributeSegments(rings);
     461        TheRing.redistributeSegments(rings);
    462462        List<Command> commands = new ArrayList<Command>();
    463463        List<Relation> relations = new ArrayList<Relation>();
     
    911911    }
    912912   
    913     /**
    914      * Tries to arrange segments in order for each ring to have at least one.
    915      */
    916     public static void redistributeSegments( List<TheRing> rings ) {
    917         // todo
    918     }
    919    
    920913    public static class TheRing {
    921914        private Way source;
     
    930923       
    931924        public void collide( TheRing other ) {
    932             System.out.println("Ring 1: " + this);
    933             System.out.println("Ring 2: " + other);
    934925            List<Node> intersectionNodes = new ArrayList<Node>();
    935926            List<RingSegment> segmentsList1 = new ArrayList<RingSegment>(segments);
    936927            List<RingSegment> segmentsList2 = new ArrayList<RingSegment>(other.segments);
     928            boolean collideNoted = false;
    937929            for( int i = 0; i < segmentsList1.size(); i++ ) {
    938930                if( !segmentsList1.get(i).isReference() )
     
    953945                        if( colliding )
    954946                            intersectionNodes.add(nodes2.get(nodes2.size()-1));
    955                         // todo: when an intersection of two rings spans a ring's beginning
     947                        // when an intersection of two rings spans a ring's beginning
    956948                        if( segmentsList1.get(i).isRing() && segmentsList2.get(j).isRing() && intersectionNodes.contains(nodes2.get(0)) && intersectionNodes.contains(nodes2.get(nodes2.size()-1)) ) {
    957949                            intersectionNodes.remove(0);
     
    959951                            intersectionNodes.add(intersectionNodes.get(0));
    960952                            intersectionNodes.remove(0);
     953                        }
     954                        if( !collideNoted && !intersectionNodes.isEmpty() ) {
     955                            System.out.println("Rings " + this + " and " + other + " collide.");
     956                            collideNoted = true;
    961957                        }
    962958                        System.out.print("Intersection nodes for segments " + segmentsList1.get(i) + " and " + segmentsList2.get(j) + ": ");
     
    977973                        while( ni+1 < intersectionNodes.size() ) {
    978974                            if( !segmentsList1.get(i).isReferencingEqual(segmentsList2.get(j)) ) {
    979                                 System.out.println("Splitting segment 1: " + segmentsList1.get(i));
    980                                 System.out.println("Splitting segment 2: " + segmentsList2.get(j));
    981975                                boolean[] isarc = new boolean[] {
    982976                                    segments.size() == 1 && !segments.get(0).isRing(),
     
    985979                                RingSegment segment = splitRingAt(i, intersectionNodes.get(ni), intersectionNodes.get(ni+1));
    986980                                RingSegment otherSegment = other.splitRingAt(j, intersectionNodes.get(ni), intersectionNodes.get(ni+1));
    987                                 if( !isarc[0] && !isarc[1] )
    988                                     segment.makeReference(otherSegment);
    989                                 else {
     981                                if( !isarc[0] && !isarc[1] ) {
     982                                    if( segments.size() > 2 )
     983                                        segment.makeReference(otherSegment);
     984                                    else {
     985                                        // this ring was a ring, and we're not sure "segment" is a correct segment
     986                                        if( segments.get(0).getNodes().size() == otherSegment.getNodes().size() &&
     987                                                (segments.get(0).getNodes().get(1).equals(otherSegment.getNodes().get(1))) ||
     988                                                (segments.get(0).getNodes().get(segments.get(0).getNodes().size()-2).equals(otherSegment.getNodes().get(1))))
     989                                            segments.get(0).makeReference(otherSegment);
     990                                        else
     991                                            segments.get(1).makeReference(otherSegment);
     992                                    }
     993                                } else {
    990994                                    // 1. A ring is an arc. It should have only 2 segments after this
    991995                                    // 2. But it has one, so add otherSegment as the second.
    992                                     // todo: determine which segment!
     996                                    // 3. determine which segment!
    993997                                    if( isarc[0] ) {
    994998                                        if( other.segments.size() > 2 )
     
    10201024                }
    10211025            }
    1022             System.out.println("Resulting ring 1: " + this);
    1023             System.out.println("Resulting ring 2: " + other);
    10241026        }
    10251027       
     
    10521054            if( thirdPart != null )
    10531055                segments.add(pos++, thirdPart);
    1054             for( int i = segmentIndex; i < pos; i++ )
    1055                 System.out.println("Split result "+(i-segmentIndex+1) + ": "+segments.get(i));
    10561056            RingSegment result = isRing || secondPart == null ? segment : secondPart;
    10571057            System.out.println("Returning segment " + result);
    10581058            return result;
     1059        }
     1060
     1061        /**
     1062         * Tries to arrange segments in order for each ring to have at least one.
     1063         * Also, sets source way for all rings.
     1064         *
     1065         * This method should be called, even if there is just one ring.
     1066         */
     1067        public static void redistributeSegments( List<TheRing> rings ) {
     1068            // build segments map
     1069            Map<RingSegment, TheRing> segmentMap = new HashMap<RingSegment, TheRing>();
     1070            for( TheRing ring : rings )
     1071                for( RingSegment seg : ring.segments )
     1072                    if( !seg.isReference())
     1073                        segmentMap.put(seg, ring);
     1074           
     1075            // rearrange references
     1076            for( int i = 0; i < rings.size(); i++) {
     1077                TheRing ring = rings.get(i);
     1078                if( ring.countNonReferenceSegments() == 0 ) {
     1079                    // need to find one non-reference segment
     1080                    for( RingSegment seg : ring.segments ) {
     1081                        TheRing otherRing = segmentMap.get(seg.references);
     1082                        if( otherRing.countNonReferenceSegments() > 1 ) {
     1083                            // we could check for >0, but it is prone to deadlocking
     1084                            seg.swapReference();
     1085                        }
     1086                    }
     1087                }
     1088            }
     1089
     1090            // initializing source way for each ring
     1091            for( TheRing ring : rings )
     1092                ring.putSourceWayFirst();
     1093        }
     1094       
     1095        private int countNonReferenceSegments() {
     1096            int count = 0;
     1097            for( RingSegment seg : segments )
     1098                if( !seg.isReference() )
     1099                    count++;
     1100            return count;
     1101        }
     1102       
     1103        private void putSourceWayFirst() {
     1104            for( RingSegment seg : segments ) {
     1105                if( !seg.isReference() ) {
     1106                    seg.overrideWay(source);
     1107                    return;
     1108                }
     1109            }
    10591110        }
    10601111       
     
    10761127            }
    10771128           
    1078             // todo: copy relations from source to all new ways
    1079            
     1129            // build a map of referencing relations
     1130            Map<Relation, Integer> referencingRelations = new HashMap<Relation, Integer>();
     1131            List<Command> relationCommands = new ArrayList<Command>();
     1132            for( OsmPrimitive p : source.getReferrers() ) {
     1133                if( p instanceof Relation ) {
     1134                    Relation rel = new Relation((Relation)p);
     1135                    relationCommands.add(new ChangeCommand((Relation)p, rel));
     1136                    for( int i = 0; i < rel.getMembersCount(); i++ )
     1137                        if( rel.getMember(i).getMember().equals(source) )
     1138                            referencingRelations.put(rel, Integer.valueOf(i));
     1139                }
     1140            }
     1141
    10801142            List<Command> commands = new ArrayList<Command>();
    10811143            boolean foundOwnWay = false;
    1082             Way w;
    10831144            for( RingSegment seg : segments ) {
    1084                 if( seg.isWayConstructed() || seg.isReference() || foundOwnWay ) {
    1085                     boolean needAdding = !seg.isWayConstructed();
    1086                     w = seg.constructWay(seg.isReference() ? null : sourceCopy);
    1087                     if( needAdding )
    1088                         commands.add(new AddCommand(w));
    1089                 } else {
    1090                     w = source;
     1145                boolean needAdding = !seg.isWayConstructed();
     1146                Way w = seg.constructWay(seg.isReference() ? null : sourceCopy);
     1147                if( needAdding )
     1148                    commands.add(new AddCommand(w));
     1149                if( w.equals(source) ) {
    10911150                    if( segments.size() == 1 ) {
    10921151                        // one segment means that it is a ring
     
    10961155                    } else
    10971156                        sourceCopy.setNodes(seg.getNodes());
    1098                     seg.overrideWay(source);
    10991157                    commands.add(new ChangeCommand(source, sourceCopy));
    11001158                    foundOwnWay = true;
     1159                } else {
     1160                    for( Relation rel : referencingRelations.keySet() ) {
     1161                        int relIndex = referencingRelations.get(rel);
     1162                        rel.addMember(new RelationMember(rel.getMember(relIndex).getRole(), w));
     1163                    }
    11011164                }
    11021165                relation.addMember(new RelationMember("outer", w));
     
    11041167            if( !foundOwnWay )
    11051168                commands.add(new DeleteCommand(source));
     1169            commands.addAll(relationCommands);
    11061170            commands.add(new AddCommand(relation));
    11071171            return commands;
    1108         }
    1109        
    1110         private List<Node> constructRing() {
    1111             List<Node> result = new ArrayList<Node>();
    1112             for( RingSegment segment : segments )
    1113                 result.addAll(segment.getNodes());
    1114             return result;
    11151172        }
    11161173       
Note: See TracChangeset for help on using the changeset viewer.