Ignore:
Timestamp:
2009-09-20T11:07:46+02:00 (15 years ago)
Author:
stoecker
Message:

see #3475 - patch by Petr Dlouhý - improve speed

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java

    r2070 r2166  
    44import java.util.Collection;
    55import java.util.HashSet;
     6import java.util.HashMap;
     7import java.util.Map;
    68
    79import org.openstreetmap.josm.data.osm.DataSet;
     
    1719 * Deleted objects are not collected.
    1820 *
    19  * @author imi
     21 * @author imi, Petr Dlouhý
    2022 */
    2123public class CollectBackReferencesVisitor extends AbstractVisitor {
     
    2426    private final boolean indirectRefs;
    2527
    26     /**
    27      * The result list of primitives stored here.
    28      */
    29     public final Collection<OsmPrimitive> data = new HashSet<OsmPrimitive>();
     28    private Collection<OsmPrimitive> data = new HashSet<OsmPrimitive>();
     29    private Map<OsmPrimitive, Collection<OsmPrimitive>> lookupTable = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();
    3030
    3131
    3232    /**
    3333     * Construct a back reference counter.
     34     * has time complexity O(n) - so it is appropriate not to call it in cycle
    3435     * @param ds The dataset to operate on.
    3536     */
    3637    public CollectBackReferencesVisitor(DataSet ds) {
    37         this.ds = ds;
    38         this.indirectRefs = true;
     38       this(ds, true);
    3939    }
    4040
     41    /**
     42     * Construct a back reference counter.
     43     * has time complexity O(n) - so it is appropriate not to call it in cycle
     44     * @param ds The dataset to operate on.
     45     * @param indirectRefs Make also indirect references?
     46     */
    4147    public CollectBackReferencesVisitor(DataSet ds, boolean indirectRefs) {
    42         this.ds = ds;
    43         this.indirectRefs = indirectRefs;
     48       this.ds = ds;
     49       this.indirectRefs = indirectRefs;
     50       if(ds != null)
     51          makeLookupTable();
     52    }
     53   
     54    private void makeLookupTable(){
     55       for (Way w : ds.ways) {
     56          for (Node n : w.getNodes()) {
     57             if(!lookupTable.containsKey(n)) lookupTable.put(n, new HashSet<OsmPrimitive>());
     58             lookupTable.get(n).add(w);
     59          }
     60       }
     61       for (Relation r : ds.relations) {
     62          for (RelationMember m : r.getMembers()) {
     63             OsmPrimitive o = m.getMember();
     64             if(!lookupTable.containsKey(o)) lookupTable.put(o, new HashSet<OsmPrimitive>());
     65             lookupTable.get(o).add(r);
     66          }
     67       }
    4468    }
    4569
     70    /**
     71     * Get the result collection
     72     */
     73    public Collection<OsmPrimitive> getData(){
     74       return data;
     75    }
     76
     77    /**
     78     * Initialize data before associated visit calls
     79     */
     80    public void initialize(){
     81       data = new HashSet<OsmPrimitive>();
     82    }
     83
     84    public void visit(OsmPrimitive o) {
     85       if(lookupTable.containsKey(o)){
     86          Collection<OsmPrimitive> c = lookupTable.get(o);
     87          Collection<OsmPrimitive> oldData = new HashSet<OsmPrimitive>(data);
     88          data.addAll(c);
     89          if(indirectRefs)
     90             for(OsmPrimitive oo : c)
     91                if(!oldData.contains(oo))
     92                   visit(oo);
     93       }
     94    }
     95   
    4696    public void visit(Node n) {
    47         for (Way w : ds.ways) {
    48             if (w.isDeleted() || w.incomplete) {
    49                 continue;
    50             }
    51             for (Node n2 : w.getNodes()) {
    52                 if (n == n2) {
    53                     data.add(w);
    54                     if (indirectRefs) {
    55                         visit(w);
    56                     }
    57                 }
    58             }
    59         }
    60         checkRelationMembership(n);
     97       visit((OsmPrimitive)n);
    6198    }
    6299
    63100    public void visit(Way w) {
    64         checkRelationMembership(w);
     101       visit((OsmPrimitive)w);
    65102    }
    66103
    67104    public void visit(Relation r) {
    68         checkRelationMembership(r);
    69     }
    70 
    71     private void checkRelationMembership(OsmPrimitive p) {
    72         // FIXME - this might be a candidate for optimisation
    73         // if OSM primitives are made to hold a list of back
    74         // references.
    75         for (Relation r : ds.relations) {
    76             if (r.incomplete || r.isDeleted()) {
    77                 continue;
    78             }
    79             for (RelationMember m : r.getMembers()) {
    80                 if (m.getMember() == p) {
    81                     if (!data.contains(r)) {
    82                         data.add(r);
    83                         if (indirectRefs) {
    84                             // move up the tree (there might be relations
    85                             // referring to this relation)
    86                             checkRelationMembership(r);
    87                         }
    88                     }
    89                     break;
    90                 }
    91             }
    92         }
     105       visit((OsmPrimitive)r);
    93106    }
    94107}
Note: See TracChangeset for help on using the changeset viewer.