Ignore:
Timestamp:
2013-12-31T14:35:34+01:00 (10 years ago)
Author:
simon04
Message:

see #6536 - Refactor crossing way test in order to decrease memory footprint

Drop data structure ExtendedSegment and obtain needed values on demand
from the way tags.

Location:
trunk/src/org/openstreetmap/josm/data
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/Preferences.java

    r6578 r6580  
    871871        String colStr = specName != null ? get("color."+specName) : "";
    872872        if(colStr.isEmpty()) {
    873             colStr = get("color."+colKey, ColorHelper.color2html(def));
     873            colStr = get("color." + colKey, "");
    874874        }
    875875        return colStr.isEmpty() ? def : ColorHelper.html2color(colStr);
  • trunk/src/org/openstreetmap/josm/data/osm/WaySegment.java

    r6380 r6580  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.osm;
     3
     4import java.awt.geom.Line2D;
    35
    46/**
     
    6365        return equals(o) ? 0 : toWay().compareTo(o.toWay());
    6466    }
     67
     68    /**
     69     * Checks whether this segment crosses other segment
     70     *
     71     * @param s2 The other segment
     72     * @return true if both segments crosses
     73     */
     74    public boolean intersects(WaySegment s2) {
     75        if (getFirstNode().equals(s2.getFirstNode()) || getSecondNode().equals(s2.getSecondNode()) ||
     76                getFirstNode().equals(s2.getSecondNode()) || getSecondNode().equals(s2.getFirstNode()))
     77            return false;
     78
     79        return Line2D.linesIntersect(
     80                getFirstNode().getEastNorth().east(), getFirstNode().getEastNorth().north(),
     81                getSecondNode().getEastNorth().east(), getSecondNode().getEastNorth().north(),
     82                s2.getFirstNode().getEastNorth().east(), s2.getFirstNode().getEastNorth().north(),
     83                s2.getSecondNode().getEastNorth().east(), s2.getSecondNode().getEastNorth().north());
     84    }
    6585}
  • trunk/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java

    r6579 r6580  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.geom.Line2D;
    76import java.awt.geom.Point2D;
    87import java.util.ArrayList;
     
    2423import org.openstreetmap.josm.data.validation.util.ValUtil;
    2524import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     25import org.openstreetmap.josm.tools.Utils;
    2626
    2727/**
     
    3434
    3535    /** All way segments, grouped by cells */
    36     private Map<Point2D,List<ExtendedSegment>> cellSegments;
     36    private Map<Point2D,List<WaySegment>> cellSegments;
    3737    /** The already detected errors */
    3838    private Set<WaySegment> errorSegments;
     
    5151    public void startTest(ProgressMonitor monitor) {
    5252        super.startTest(monitor);
    53         cellSegments = new HashMap<Point2D,List<ExtendedSegment>>(1000);
     53        cellSegments = new HashMap<Point2D,List<WaySegment>>(1000);
    5454        errorSegments = new HashSet<WaySegment>();
    5555        seenWays = new HashMap<List<Way>, List<WaySegment>>(50);
     
    6464    }
    6565
    66     private String getLayer(OsmPrimitive w) {
     66    static String getLayer(OsmPrimitive w) {
    6767        String layer1 = w.get("layer");
    6868        if ("0".equals(layer1)) {
     
    8181    }
    8282
     83    static boolean isCoastline(OsmPrimitive w) {
     84        return w.hasTag("natural", "water", "coastline") || w.hasTag("landuse", "reservoir");
     85    }
     86
     87    static boolean isSubwayOrTram(OsmPrimitive w) {
     88        return w.hasTag("railway", "subway", "tram");
     89    }
     90
     91    static boolean isProposedOrAbandoned(OsmPrimitive w) {
     92        return w.hasTag("highway", "proposed") || w.hasTag("railway", "proposed", "abandoned");
     93    }
     94
     95    boolean ignoreWaySegmentCombination(Way w1, Way w2) {
     96        if (!Utils.equal(getLayer(w1), getLayer(w2))) {
     97            return true;
     98        }
     99        if (w1.hasKey("highway") && w2.hasKey("highway") && !Utils.equal(w1.get("level"), w2.get("level"))) {
     100            return true;
     101        }
     102        if (isSubwayOrTram(w2)) {
     103            return true;
     104        }
     105        if (isCoastline(w1) != isCoastline(w2)) {
     106            return true;
     107        }
     108        if ((w1.hasTag("waterway", "river") && w2.hasTag("waterway", "riverbank"))
     109         || (w2.hasTag("waterway", "river") && w1.hasTag("waterway", "riverbank"))) {
     110            return true;
     111        }
     112        if (isProposedOrAbandoned(w2)) {
     113            return true;
     114        }
     115        return false;
     116    }
     117
     118    String createMessage(Way w1, Way w2) {
     119        if (isBuilding(w1)) {
     120            return ("Crossing buildings");
     121        } else if (w1.hasKey("waterway") && w2.hasKey("waterway")) {
     122            return tr("Crossing waterways");
     123        } else if ((w1.hasKey("highway") && w2.hasKey("waterway"))
     124                || (w2.hasKey("highway") && w1.hasKey("waterway"))) {
     125            return tr("Crossing waterway/highway");
     126        } else {
     127            return tr("Crossing ways");
     128        }
     129    }
     130
     131    @Override
     132    public boolean isPrimitiveUsable(OsmPrimitive w) {
     133        return super.isPrimitiveUsable(w)
     134                && !isProposedOrAbandoned(w)
     135                && (w.hasKey("highway")
     136                || w.hasKey("waterway")
     137                || (w.hasKey("railway") && !isSubwayOrTram(w))
     138                || isCoastline(w)
     139                || isBuilding(w));
     140    }
     141
     142
    83143    @Override
    84144    public void visit(Way w) {
    85         if(!w.isUsable())
    86             return;
    87 
    88         String natural1 = w.get("natural");
    89         String landuse1 = w.get("landuse");
    90         boolean isCoastline1 = "water".equals(natural1) || "coastline".equals(natural1) || "reservoir".equals(landuse1);
    91         String highway1 = w.get("highway");
    92         String railway1 = w.get("railway");
    93         boolean isSubway1 = "subway".equals(railway1);
    94         boolean isTram1 = "tram".equals(railway1);
    95         boolean isBuilding = isBuilding(w);
    96         String waterway1 = w.get("waterway");
    97 
    98         if (w.get("highway") == null && w.get("waterway") == null
    99                 && (railway1 == null || isSubway1 || isTram1)
    100                 && !isCoastline1 && !isBuilding)
    101             return;
    102 
    103         String level1 = w.get("level");
    104         String layer1 = getLayer(w);
    105145
    106146        int nodesSize = w.getNodesCount();
    107147        for (int i = 0; i < nodesSize - 1; i++) {
    108             WaySegment ws = new WaySegment(w, i);
    109             ExtendedSegment es1 = new ExtendedSegment(ws, layer1, highway1, railway1, isCoastline1, waterway1, level1);
    110             for (List<ExtendedSegment> segments : getSegments(es1.n1, es1.n2)) {
    111                 for (ExtendedSegment es2 : segments) {
     148            final WaySegment es1 = new WaySegment(w, i);
     149            for (List<WaySegment> segments : getSegments(es1.getFirstNode(), es1.getSecondNode())) {
     150                for (WaySegment es2 : segments) {
    112151                    List<Way> prims;
    113152                    List<WaySegment> highlight;
    114153
    115                     if (errorSegments.contains(ws) && errorSegments.contains(es2.ws)) {
     154                    if (errorSegments.contains(es1) && errorSegments.contains(es2)
     155                            || !es1.intersects(es2)
     156                            || ignoreWaySegmentCombination(es1.way, es2.way)) {
    116157                        continue;
    117158                    }
    118159
    119                     String level2 = es2.level;
    120                     String layer2 = es2.layer;
    121                     String highway2 = es2.highway;
    122                     String railway2 = es2.railway;
    123                     boolean isCoastline2 = es2.coastline;
    124                     if (layer1 == null ? layer2 != null : !layer1.equals(layer2)) {
    125                         continue;
    126                     }
    127                     // Ignore indoor highways on different levels
    128                     if (highway1 != null && highway2 != null && level1 != null && level2 != null && !level1.equals(level2)) {
    129                         continue;
    130                     }
    131 
    132                     if (!es1.intersects(es2) ) {
    133                         continue;
    134                     }
    135                     if (isSubway1 && "subway".equals(railway2)) {
    136                         continue;
    137                     }
    138                     if (isTram1 && "tram".equals(railway2)) {
    139                         continue;
    140                     }
    141 
    142                     if (isCoastline1 != isCoastline2) {
    143                         continue;
    144                     }
    145                     if (("river".equals(waterway1) && "riverbank".equals(es2.waterway))
    146                             || ("riverbank".equals(waterway1) && "river".equals(es2.waterway))) {
    147                         continue;
    148                     }
    149 
    150                     if ("proposed".equals(es1.highway) || "proposed".equals(highway2)
    151                      || "proposed".equals(es1.railway) || "proposed".equals(railway2)
    152                      || "abandoned".equals(es1.railway) || "abandoned".equals(railway2)) {
    153                         continue;
    154                     }
    155 
    156                     prims = Arrays.asList(es1.ws.way, es2.ws.way);
     160                    prims = Arrays.asList(es1.way, es2.way);
    157161                    if ((highlight = seenWays.get(prims)) == null) {
    158162                        highlight = new ArrayList<WaySegment>();
    159                         highlight.add(es1.ws);
    160                         highlight.add(es2.ws);
    161 
    162                         String message;
    163                         if (isBuilding) {
    164                             message = tr("Crossing buildings");
    165                         } else if ((es1.waterway != null && es2.waterway != null)) {
    166                             message = tr("Crossing waterways");
    167                         } else if ((es1.waterway != null && es2.highway != null)
    168                                 || (es2.waterway != null && es1.highway != null)) {
    169                             message = tr("Crossing waterway/highway");
    170                         } else {
    171                             message = tr("Crossing ways");
    172                         }
    173 
     163                        highlight.add(es1);
     164                        highlight.add(es2);
     165
     166                        final String message = createMessage(es1.way, es2.way);
    174167                        errors.add(new TestError(this, Severity.WARNING,
    175168                                message,
     
    179172                        seenWays.put(prims, highlight);
    180173                    } else {
    181                         highlight.add(es1.ws);
    182                         highlight.add(es2.ws);
     174                        highlight.add(es1);
     175                        highlight.add(es2);
    183176                    }
    184177                }
     
    196189     * @return A list with all the cells the segment crosses
    197190     */
    198     public List<List<ExtendedSegment>> getSegments(Node n1, Node n2) {
    199 
    200         List<List<ExtendedSegment>> cells = new ArrayList<List<ExtendedSegment>>();
    201         for(Point2D cell : ValUtil.getSegmentCells(n1, n2, OsmValidator.griddetail)) {
    202             List<ExtendedSegment> segments = cellSegments.get(cell);
     191    public List<List<WaySegment>> getSegments(Node n1, Node n2) {
     192
     193        List<List<WaySegment>> cells = new ArrayList<List<WaySegment>>();
     194        for (Point2D cell : ValUtil.getSegmentCells(n1, n2, OsmValidator.griddetail)) {
     195            List<WaySegment> segments = cellSegments.get(cell);
    203196            if (segments == null) {
    204                 segments = new ArrayList<ExtendedSegment>();
     197                segments = new ArrayList<WaySegment>();
    205198                cellSegments.put(cell, segments);
    206199            }
     
    210203    }
    211204
    212     /**
    213      * A way segment with some additional information
    214      */
    215     public static class ExtendedSegment {
    216         private final Node n1, n2;
    217 
    218         private final WaySegment ws;
    219 
    220         /** The layer */
    221         private final String layer;
    222 
    223         /** The highway type */
    224         private final String highway;
    225 
    226         /** The railway type */
    227         private final String railway;
    228 
    229         /** The waterway type */
    230         private final String waterway;
    231 
    232         /** The coastline type */
    233         private final boolean coastline;
    234 
    235         /** The level, only considered for indoor highways */
    236         private final String level;
    237 
    238         /**
    239          * Constructor
    240          * @param ws The way segment
    241          * @param layer The layer of the way this segment is in
    242          * @param highway The highway type of the way this segment is in
    243          * @param railway The railway type of the way this segment is in
    244          * @param coastline The coastline flag of the way the segment is in
    245          * @param waterway The waterway type of the way this segment is in
    246          * @param level The level of the way this segment is in
    247          */
    248         public ExtendedSegment(WaySegment ws, String layer, String highway, String railway, boolean coastline, String waterway, String level) {
    249             this.ws = ws;
    250             this.n1 = ws.way.getNodes().get(ws.lowerIndex);
    251             this.n2 = ws.way.getNodes().get(ws.lowerIndex + 1);
    252             this.layer = layer;
    253             this.highway = highway;
    254             this.railway = railway;
    255             this.coastline = coastline;
    256             this.waterway = waterway;
    257             this.level = level;
    258         }
    259 
    260         /**
    261          * Checks whether this segment crosses other segment
    262          * @param s2 The other segment
    263          * @return true if both segments crosses
    264          */
    265         public boolean intersects(ExtendedSegment s2) {
    266             if (n1.equals(s2.n1) || n2.equals(s2.n2) ||
    267                     n1.equals(s2.n2) || n2.equals(s2.n1))
    268                 return false;
    269 
    270             return Line2D.linesIntersect(
    271                     n1.getEastNorth().east(), n1.getEastNorth().north(),
    272                     n2.getEastNorth().east(), n2.getEastNorth().north(),
    273                     s2.n1.getEastNorth().east(), s2.n1.getEastNorth().north(),
    274                     s2.n2.getEastNorth().east(), s2.n2.getEastNorth().north());
    275         }
    276     }
    277205}
Note: See TracChangeset for help on using the changeset viewer.