Ticket #13165: 13165_v4.patch

File 13165_v4.patch, 8.0 KB (added by GerdP, 5 weeks ago)
  • src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

     
    9494public class MapCSSTagChecker extends Test.TagTest {
    9595    MapCSSTagCheckerIndex indexData;
    9696    final Set<OsmPrimitive> tested = new HashSet<>();
     97    final Map<IPrimitive, Area> mpAreaCache = new HashMap<>();
    9798
    9899    /**
    99100    * A grouped MapCSSRule with multiple selectors for a single declaration.
     
    708709        MapCSSRuleIndex matchingRuleIndex = indexData.get(p);
    709710
    710711        Environment env = new Environment(p, new MultiCascade(), Environment.DEFAULT_LAYER, null);
     712        env.mpAreaCache = mpAreaCache;
    711713        // the declaration indices are sorted, so it suffices to save the last used index
    712714        Declaration lastDeclUsed = null;
    713715
     
    774776        return false;
    775777    }
    776778
    777     private static Collection<TestError> getErrorsForPrimitive(OsmPrimitive p, boolean includeOtherSeverity,
     779    private Collection<TestError> getErrorsForPrimitive(OsmPrimitive p, boolean includeOtherSeverity,
    778780            Collection<Set<TagCheck>> checksCol) {
     781        // this variant is only used by the assertion tests
    779782        final List<TestError> r = new ArrayList<>();
    780783        final Environment env = new Environment(p, new MultiCascade(), Environment.DEFAULT_LAYER, null);
     784        env.mpAreaCache = mpAreaCache;
    781785        for (Set<TagCheck> schecks : checksCol) {
    782786            for (TagCheck check : schecks) {
    783787                boolean ignoreError = Severity.OTHER == check.getSeverity() && !includeOtherSeverity;
     
    991995            indexData = new MapCSSTagCheckerIndex(checks, includeOtherSeverityChecks(), MapCSSTagCheckerIndex.ALL_TESTS);
    992996        }
    993997        tested.clear();
     998        mpAreaCache.clear();
    994999    }
    9951000
    9961001    @Override
     
    10251030        super.endTest();
    10261031        // no need to keep the index, it is quickly build and doubles the memory needs
    10271032        indexData = null;
     1033        mpAreaCache.clear();
    10281034    }
    10291035}
  • src/org/openstreetmap/josm/gui/mappaint/Environment.java

     
    7676    public Map<IPrimitive, Area> intersections;
    7777
    7878    /**
     79     * Cache for multipolygon areas, can be null, used with CrossingFinder
     80     */
     81    public Map<IPrimitive, Area> mpAreaCache;
     82
     83    /**
    7984     * Creates a new uninitialized environment.
    8085     */
    8186    public Environment() {
     
    126131        this.context = other.getContext();
    127132        this.children = other.children == null ? null : new LinkedHashSet<>(other.children);
    128133        this.intersections = other.intersections == null ? null : new HashMap<>(other.intersections);
     134        this.mpAreaCache = other.mpAreaCache; // don't create a copy
    129135    }
    130136
    131137    /**
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java

     
    305305
    306306            private CrossingFinder(Environment e) {
    307307                super(e);
    308                 CheckParameterUtil.ensureThat(e.osm instanceof IWay, "Only ways are supported");
     308                CheckParameterUtil.ensureThat(isArea(e.osm), "Only areas are supported");
    309309                layer = OsmUtils.getLayer(e.osm);
    310310            }
    311311
    312312            @Override
    313             public void visit(IWay<?> w) {
    314                 if (Objects.equals(layer, OsmUtils.getLayer(w))
    315                     && left.matches(new Environment(w).withParent(e.osm))
    316                     && e.osm instanceof IWay) {
    317                     if (area == null) {
    318                         area = Geometry.getAreaEastNorth(e.osm);
    319                     }
    320                     Pair<PolygonIntersection, Area> is = Geometry.polygonIntersectionResult(
    321                             Geometry.getAreaEastNorth(w), area, Geometry.INTERSECTION_EPS_EAST_NORTH);
    322                     if (Geometry.PolygonIntersection.CROSSING == is.a) {
    323                         addToChildren(e, w);
    324                         // store intersection area to improve highlight and zoom to problem
    325                         if (e.intersections == null) {
    326                             e.intersections = new HashMap<>();
     313            public void visit(Collection<? extends IPrimitive> primitives) {
     314                List<? extends IPrimitive> toIgnore;
     315                if (e.osm instanceof Relation) {
     316                    toIgnore = ((IRelation<?>) e.osm).getMemberPrimitivesList();
     317                } else
     318                    toIgnore = null;
     319                for (IPrimitive p : primitives) {
     320                    if (isPrimitiveUsable(p) && Objects.equals(layer, OsmUtils.getLayer(p))
     321                            && left.matches(new Environment(p).withParent(e.osm)) && isArea(p)
     322                            && (toIgnore == null || !toIgnore.contains(p))) {
     323                        if (area == null) {
     324                            area = getAreaEastNorth(e.osm, e);
    327325                        }
    328                         e.intersections.put(w, is.b);
     326                        Pair<PolygonIntersection, Area> is = Geometry.polygonIntersectionResult(getAreaEastNorth(p, e),
     327                                area, Geometry.INTERSECTION_EPS_EAST_NORTH);
     328                        if (Geometry.PolygonIntersection.CROSSING == is.a) {
     329                            addToChildren(e, p);
     330                            // store intersection area to improve highlight and zoom to problem
     331                            if (e.intersections == null) {
     332                                e.intersections = new HashMap<>();
     333                            }
     334                            e.intersections.put(p, is.b);
     335                        }
    329336                    }
    330337                }
    331338            }
     
    452459                visitBBox(e, insideOrEqualFinder);
    453460                return ChildOrParentSelectorType.SUPERSET_OR_EQUAL == type ? e.children != null : e.children == null;
    454461
    455             } else if (ChildOrParentSelectorType.CROSSING == type && e.osm instanceof IWay) {
     462            } else if (ChildOrParentSelectorType.CROSSING == type) {
    456463                e.parent = e.osm;
    457                 if (right instanceof OptimizedGeneralSelector
    458                         && e.osm.getDataSet() != null
    459                         && ((OptimizedGeneralSelector) right).matchesBase(OsmPrimitiveType.WAY)) {
     464                if (e.osm.getDataSet() != null && isArea(e.osm)) {
    460465                    final CrossingFinder crossingFinder = new CrossingFinder(e);
    461                     crossingFinder.visit(e.osm.getDataSet().searchWays(e.osm.getBBox()));
     466                    visitBBox(e, crossingFinder);
     467                    return e.children != null;
    462468                }
    463469                return e.children != null;
    464470            } else if (ChildOrParentSelectorType.SIBLING == type) {
     
    538544            return new ChildOrParentSelector(left, link, right.optimizedBaseCheck(), type);
    539545        }
    540546
     547        private Area getAreaEastNorth(IPrimitive p, Environment e) {
     548            if (e.mpAreaCache != null && p.isMultipolygon()) {
     549                Area area = e.mpAreaCache.get(p);
     550                if (area == null) {
     551                    area = Geometry.getAreaEastNorth(p);
     552                    e.mpAreaCache.put(p, area);
     553                }
     554                return area;
     555            }
     556            return Geometry.getAreaEastNorth(p);
     557        }
     558
    541559        @Override
    542560        public String toString() {
    543561            return left.toString() + ' ' + (ChildOrParentSelectorType.PARENT == type ? '<' : '>') + link + ' ' + right;