Changeset 4630 in josm


Ignore:
Timestamp:
Dec 4, 2011 12:30:57 AM (18 months ago)
Author:
Don-vip
Message:

see #6987 - final (?) performance tweaks on multipolygon cache

Location:
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/relations
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/Multipolygon.java

    r4629 r4630  
    1010import java.util.Collection; 
    1111import java.util.Collections; 
     12import java.util.HashSet; 
     13import java.util.Iterator; 
    1214import java.util.List; 
     15import java.util.Set; 
    1316 
    1417import org.openstreetmap.josm.Main; 
    1518import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent; 
    1619import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener; 
     20import org.openstreetmap.josm.data.osm.DataSet; 
    1721import org.openstreetmap.josm.data.osm.Node; 
     22import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 
    1823import org.openstreetmap.josm.data.osm.Relation; 
    1924import org.openstreetmap.josm.data.osm.RelationMember; 
    2025import org.openstreetmap.josm.data.osm.Way; 
    2126import org.openstreetmap.josm.data.osm.event.NodeMovedEvent; 
     27import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent; 
    2228import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData.Intersection; 
    2329 
     
    150156    public static class JoinedWay { 
    151157        private final List<Node> nodes; 
     158        private final Collection<Long> wayIds; 
    152159        private final boolean selected; 
    153160 
    154         public JoinedWay(List<Node> nodes, boolean selected) { 
     161        public JoinedWay(List<Node> nodes, Collection<Long> wayIds, boolean selected) { 
    155162            this.nodes = nodes; 
     163            this.wayIds = wayIds; 
    156164            this.selected = selected; 
    157165        } 
     
    161169        } 
    162170 
     171        public Collection<Long> getWayIds() { 
     172            return wayIds; 
     173        } 
     174 
    163175        public boolean isSelected() { 
    164176            return selected; 
     
    173185        public enum Intersection {INSIDE, OUTSIDE, CROSSING} 
    174186 
    175         public final Path2D.Double poly; 
     187        private final Path2D.Double poly; 
    176188        public boolean selected; 
    177189        private Rectangle2D bounds; 
    178         private final Collection<Way> ways; 
     190        private final Collection<Long> wayIds; 
    179191        private final List<Node> nodes; 
    180192        private final List<PolyData> inners; 
    181193 
    182         public PolyData(JoinedWay joinedWay, Collection<Way> refWays) { 
    183             this(joinedWay.getNodes(), joinedWay.isSelected(), refWays); 
    184         } 
    185  
    186         public PolyData(List<Node> nodes, boolean selected, Collection<Way> refWays) { 
    187             this.ways = Collections.unmodifiableCollection(refWays); 
    188             this.nodes = Collections.unmodifiableList(nodes); 
     194        public PolyData(Way closedWay) { 
     195            this(closedWay.getNodes(), closedWay.isSelected(), Collections.singleton(closedWay.getId())); 
     196        } 
     197 
     198        public PolyData(JoinedWay joinedWay) { 
     199            this(joinedWay.getNodes(), joinedWay.isSelected(), joinedWay.getWayIds()); 
     200        } 
     201 
     202        private PolyData(List<Node> nodes, boolean selected, Collection<Long> wayIds) { 
     203            this.wayIds = Collections.unmodifiableCollection(wayIds); 
     204            this.nodes = nodes; 
    189205            this.selected = selected; 
    190206            this.inners = new ArrayList<Multipolygon.PolyData>(); 
     
    196212        private void buildPoly() { 
    197213            boolean initial = true; 
    198             for (Node n : nodes) 
    199             { 
     214            for (Node n : nodes) { 
    200215                Point2D p = n.getEastNorth(); 
    201216                if (initial) { 
     
    215230            this.selected = copy.selected; 
    216231            this.poly = (Double) copy.poly.clone(); 
    217             this.ways = Collections.unmodifiableCollection(copy.ways); 
    218             this.nodes = Collections.unmodifiableList(copy.nodes); 
     232            this.wayIds = Collections.unmodifiableCollection(copy.wayIds); 
     233            this.nodes = new ArrayList<Node>(copy.nodes); 
    219234            this.inners = new ArrayList<Multipolygon.PolyData>(copy.inners); 
    220235        } 
     
    259274        } 
    260275         
    261         public Collection<Way> getWays() { 
    262             return ways; 
     276        public Collection<Long> getWayIds() { 
     277            return wayIds; 
     278        } 
     279         
     280        private void resetNodes() { 
     281            if (!nodes.isEmpty()) { 
     282                DataSet ds = nodes.get(0).getDataSet(); 
     283                nodes.clear(); 
     284                if (wayIds.size() == 1) { 
     285                    Way w = (Way) ds.getPrimitiveById(wayIds.iterator().next(), OsmPrimitiveType.WAY); 
     286                    nodes.addAll(w.getNodes()); 
     287                } else { 
     288                    List<Way> waysToJoin = new ArrayList<Way>(); 
     289                    for (Iterator<Long> it = wayIds.iterator(); it.hasNext(); ) { 
     290                        waysToJoin.add((Way) ds.getPrimitiveById(it.next(), OsmPrimitiveType.WAY)); 
     291                    } 
     292                    nodes.addAll(joinWays(waysToJoin).iterator().next().getNodes()); 
     293                } 
     294                resetPoly(); 
     295            } 
    263296        } 
    264297         
     
    280313            if (nodes.contains(n) || innerChanged) { 
    281314                resetPoly(); 
     315            } 
     316        } 
     317         
     318        public void wayNodesChanged(WayNodesChangedEvent event) { 
     319            final Long wayId = event.getChangedWay().getId(); 
     320            boolean innerChanged = false; 
     321            for (PolyData inner : inners) { 
     322                if (inner.wayIds.contains(wayId)) { 
     323                    inner.resetNodes(); 
     324                    innerChanged = true; 
     325                } 
     326            } 
     327            if (wayIds.contains(wayId) || innerChanged) { 
     328                resetNodes(); 
    282329            } 
    283330        } 
     
    329376        for (Way way: ways) { 
    330377            if (way.isClosed()) { 
    331                 result.add(new PolyData(way.getNodes(), way.isSelected(), Collections.singleton(way))); 
     378                result.add(new PolyData(way)); 
    332379            } else { 
    333380                waysToJoin.add(way); 
     
    336383 
    337384        for (JoinedWay jw: joinWays(waysToJoin)) { 
    338             result.add(new PolyData(jw, waysToJoin)); 
    339         } 
    340     } 
    341  
    342     public static Collection<JoinedWay> joinWays(Collection<Way> join) 
     385            result.add(new PolyData(jw)); 
     386        } 
     387    } 
     388 
     389    public static Collection<JoinedWay> joinWays(Collection<Way> waysToJoin) 
    343390    { 
    344         Collection<JoinedWay> res = new ArrayList<JoinedWay>(); 
    345         Way[] joinArray = join.toArray(new Way[join.size()]); 
    346         int left = join.size(); 
    347         while(left != 0) 
    348         { 
     391        final Collection<JoinedWay> result = new ArrayList<JoinedWay>(); 
     392        final Way[] joinArray = waysToJoin.toArray(new Way[waysToJoin.size()]); 
     393        int left = waysToJoin.size(); 
     394        while (left > 0) { 
    349395            Way w = null; 
    350396            boolean selected = false; 
    351             List<Node> n = null; 
     397            List<Node> nodes = null; 
     398            Set<Long> wayIds = new HashSet<Long>(); 
    352399            boolean joined = true; 
    353             while(joined && left != 0) 
    354             { 
     400            while (joined && left > 0) { 
    355401                joined = false; 
    356                 for(int i = 0; i < joinArray.length && left != 0; ++i) 
    357                 { 
    358                     if(joinArray[i] != null) 
    359                     { 
     402                for (int i = 0; i < joinArray.length && left != 0; ++i) { 
     403                    if (joinArray[i] != null) { 
    360404                        Way c = joinArray[i]; 
    361                         if(w == null) 
    362                         { w = c; selected = w.isSelected(); joinArray[i] = null; --left; } 
    363                         else 
    364                         { 
     405                        if (w == null) { 
     406                            w = c; 
     407                            selected = w.isSelected(); 
     408                            joinArray[i] = null; 
     409                            --left; 
     410                        } else { 
    365411                            int mode = 0; 
    366412                            int cl = c.getNodesCount()-1; 
    367413                            int nl; 
    368                             if(n == null) 
    369                             { 
     414                            if (nodes == null) { 
    370415                                nl = w.getNodesCount()-1; 
    371                                 if(w.getNode(nl) == c.getNode(0)) { 
     416                                if (w.getNode(nl) == c.getNode(0)) { 
    372417                                    mode = 21; 
    373                                 } else if(w.getNode(nl) == c.getNode(cl)) { 
     418                                } else if (w.getNode(nl) == c.getNode(cl)) { 
    374419                                    mode = 22; 
    375                                 } else if(w.getNode(0) == c.getNode(0)) { 
     420                                } else if (w.getNode(0) == c.getNode(0)) { 
    376421                                    mode = 11; 
    377                                 } else if(w.getNode(0) == c.getNode(cl)) { 
     422                                } else if (w.getNode(0) == c.getNode(cl)) { 
    378423                                    mode = 12; 
    379424                                } 
    380                             } 
    381                             else 
    382                             { 
    383                                 nl = n.size()-1; 
    384                                 if(n.get(nl) == c.getNode(0)) { 
     425                            } else { 
     426                                nl = nodes.size()-1; 
     427                                if (nodes.get(nl) == c.getNode(0)) { 
    385428                                    mode = 21; 
    386                                 } else if(n.get(0) == c.getNode(cl)) { 
     429                                } else if (nodes.get(0) == c.getNode(cl)) { 
    387430                                    mode = 12; 
    388                                 } else if(n.get(0) == c.getNode(0)) { 
     431                                } else if (nodes.get(0) == c.getNode(0)) { 
    389432                                    mode = 11; 
    390                                 } else if(n.get(nl) == c.getNode(cl)) { 
     433                                } else if (nodes.get(nl) == c.getNode(cl)) { 
    391434                                    mode = 22; 
    392435                                } 
    393436                            } 
    394                             if(mode != 0) 
    395                             { 
     437                            if (mode != 0) { 
    396438                                joinArray[i] = null; 
    397439                                joined = true; 
    398                                 if(c.isSelected()) { 
     440                                if (c.isSelected()) { 
    399441                                    selected = true; 
    400442                                } 
    401443                                --left; 
    402                                 if(n == null) { 
    403                                     n = w.getNodes(); 
     444                                if (nodes == null) { 
     445                                    nodes = w.getNodes(); 
     446                                    wayIds.add(w.getId()); 
    404447                                } 
    405                                 n.remove((mode == 21 || mode == 22) ? nl : 0); 
    406                                 if(mode == 21) { 
    407                                     n.addAll(c.getNodes()); 
    408                                 } else if(mode == 12) { 
    409                                     n.addAll(0, c.getNodes()); 
    410                                 } else if(mode == 22) 
    411                                 { 
    412                                     for(Node node : c.getNodes()) { 
    413                                         n.add(nl, node); 
     448                                nodes.remove((mode == 21 || mode == 22) ? nl : 0); 
     449                                if (mode == 21) { 
     450                                    nodes.addAll(c.getNodes()); 
     451                                } else if (mode == 12) { 
     452                                    nodes.addAll(0, c.getNodes()); 
     453                                } else if (mode == 22) { 
     454                                    for (Node node : c.getNodes()) { 
     455                                        nodes.add(nl, node); 
     456                                    } 
     457                                } else /* mode == 11 */ { 
     458                                    for (Node node : c.getNodes()) { 
     459                                        nodes.add(0, node); 
    414460                                    } 
    415461                                } 
    416                                 else /* mode == 11 */ 
    417                                 { 
    418                                     for(Node node : c.getNodes()) { 
    419                                         n.add(0, node); 
    420                                     } 
    421                                 } 
     462                                wayIds.add(c.getId()); 
    422463                            } 
    423464                        } 
     
    426467            } /* while(joined) */ 
    427468 
    428             if (n == null) { 
    429                 n = w.getNodes(); 
    430             } 
    431  
    432             res.add(new JoinedWay(n, selected)); 
     469            if (nodes == null) { 
     470                nodes = w.getNodes(); 
     471                wayIds.add(w.getId()); 
     472            } 
     473 
     474            result.add(new JoinedWay(nodes, wayIds, selected)); 
    433475        } /* while(left != 0) */ 
    434476 
    435         return res; 
     477        return result; 
    436478    } 
    437479 
     
    521563        return combinedPolygons; 
    522564    } 
    523  
    524565} 
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java

    r4629 r4630  
    120120    } 
    121121     
    122     private final void updateMultipolygonsReferringTo(final AbstractDatasetChangedEvent event) { 
     122    private final void updateMultipolygonsReferringTo(AbstractDatasetChangedEvent event) { 
    123123        updateMultipolygonsReferringTo(event, event.getPrimitives(), event.getDataset()); 
    124124    } 
    125125 
    126126    private final void updateMultipolygonsReferringTo( 
    127             final AbstractDatasetChangedEvent event, final Collection<? extends OsmPrimitive> primitives, final DataSet ds) { 
     127            final AbstractDatasetChangedEvent event, Collection<? extends OsmPrimitive> primitives, DataSet ds) { 
    128128        updateMultipolygonsReferringTo(event, primitives, ds, null); 
    129129    } 
    130130     
    131131    private final Collection<Map<Relation, Multipolygon>> updateMultipolygonsReferringTo( 
    132             final AbstractDatasetChangedEvent event, final Collection<? extends OsmPrimitive> primitives,  
    133             final DataSet ds, final Collection<Map<Relation, Multipolygon>> initialMaps) { 
     132            AbstractDatasetChangedEvent event, Collection<? extends OsmPrimitive> primitives,  
     133            DataSet ds, Collection<Map<Relation, Multipolygon>> initialMaps) { 
    134134        Collection<Map<Relation, Multipolygon>> maps = initialMaps; 
    135135        if (primitives != null) { 
     
    158158    } 
    159159     
    160     private final void processEvent(final AbstractDatasetChangedEvent event, final Relation r, final Collection<Map<Relation, Multipolygon>> maps) { 
    161         if (event instanceof NodeMovedEvent) { 
    162             for (Map<Relation, Multipolygon> map : maps) { 
    163                 Multipolygon m = map.get(r); 
    164                 for (PolyData pd : m.getCombinedPolygons()) { 
    165                     pd.nodeMoved((NodeMovedEvent) event); 
    166                 } 
     160    private final void processEvent(AbstractDatasetChangedEvent event, Relation r, Collection<Map<Relation, Multipolygon>> maps) { 
     161        if (event instanceof NodeMovedEvent || event instanceof WayNodesChangedEvent) { 
     162            dispatchEvent(event, r, maps); 
     163        } else if (event instanceof PrimitivesRemovedEvent) { 
     164            if (event.getPrimitives().contains(r)) { 
     165                removeMultipolygonFrom(r, maps); 
    167166            } 
    168167        } else { 
    169168            // Default (non-optimal) action: remove multipolygon from cache  
    170             for (Map<Relation, Multipolygon> map : maps) { 
    171                 map.remove(r); 
    172             } 
     169            removeMultipolygonFrom(r, maps); 
     170        } 
     171    } 
     172     
     173    private final void dispatchEvent(AbstractDatasetChangedEvent event, Relation r, Collection<Map<Relation, Multipolygon>> maps) { 
     174        for (Map<Relation, Multipolygon> map : maps) { 
     175            Multipolygon m = map.get(r); 
     176            for (PolyData pd : m.getCombinedPolygons()) { 
     177                if (event instanceof NodeMovedEvent) { 
     178                    pd.nodeMoved((NodeMovedEvent) event); 
     179                } else if (event instanceof WayNodesChangedEvent) { 
     180                    pd.wayNodesChanged((WayNodesChangedEvent)event); 
     181                } 
     182            } 
     183        } 
     184    } 
     185     
     186    private final void removeMultipolygonFrom(Relation r, Collection<Map<Relation, Multipolygon>> maps) { 
     187        for (Map<Relation, Multipolygon> map : maps) { 
     188            map.remove(r); 
    173189        } 
    174190    } 
     
    181197    @Override 
    182198    public void primitivesRemoved(PrimitivesRemovedEvent event) { 
    183         updateMultipolygonsReferringTo(event);// FIXME: See if it is possible to update only concerned PolyData 
     199        updateMultipolygonsReferringTo(event); 
    184200    } 
    185201 
    186202    @Override 
    187203    public void tagsChanged(TagsChangedEvent event) { 
    188         //removeMultipolygonsReferringTo(event); 
     204        // Do nothing 
    189205    } 
    190206 
     
    196212    @Override 
    197213    public void wayNodesChanged(WayNodesChangedEvent event) { 
    198         updateMultipolygonsReferringTo(event);// FIXME: See if it is possible to update only concerned PolyData 
     214        updateMultipolygonsReferringTo(event); 
    199215    } 
    200216 
    201217    @Override 
    202218    public void relationMembersChanged(RelationMembersChangedEvent event) { 
    203         updateMultipolygonsReferringTo(event);// FIXME: See if it is possible to update only concerned PolyData 
     219        updateMultipolygonsReferringTo(event); 
    204220    } 
    205221 
    206222    @Override 
    207223    public void otherDatasetChange(AbstractDatasetChangedEvent event) { 
    208         updateMultipolygonsReferringTo(event);// FIXME: See if it is possible to update only concerned PolyData 
     224        // Do nothing 
    209225    } 
    210226 
    211227    @Override 
    212228    public void dataChanged(DataChangedEvent event) { 
    213         updateMultipolygonsReferringTo(event);// FIXME: See if it is possible to update only concerned PolyData 
     229        // Do nothing 
    214230    } 
    215231 
     
    260276                            if (multipolygon != null) { 
    261277                                for (PolyData pd : multipolygon.getCombinedPolygons()) { 
    262                                     if (pd.getWays().contains(p)) { 
     278                                    if (pd.getWayIds().contains(p.getId())) { 
    263279                                        pd.selected = true; 
    264280                                        selectedPolyData.add(pd); 
Note: See TracChangeset for help on using the changeset viewer.