001    package org.openstreetmap.josm.data.validation.tests;
002    
003    import static org.openstreetmap.josm.tools.I18n.tr;
004    
005    import java.util.ArrayList;
006    import java.util.Collection;
007    import java.util.Collections;
008    
009    import org.openstreetmap.josm.data.osm.QuadBuckets;
010    import org.openstreetmap.josm.data.osm.Way;
011    import org.openstreetmap.josm.data.validation.Severity;
012    import org.openstreetmap.josm.data.validation.Test;
013    import org.openstreetmap.josm.data.validation.TestError;
014    import org.openstreetmap.josm.gui.mappaint.ElemStyles;
015    import org.openstreetmap.josm.tools.Geometry;
016    import org.openstreetmap.josm.tools.Predicate;
017    import org.openstreetmap.josm.tools.Utils;
018    
019    public class OverlappingAreas extends Test {
020    
021        protected static final int OVERLAPPING_AREAS = 2201;
022        protected QuadBuckets<Way> index = new QuadBuckets<Way>();
023    
024        public OverlappingAreas() {
025            super(tr("Overlapping Areas"), tr("This test checks if areas overlap."));
026        }
027    
028        @Override
029        public void visit(Way w) {
030            if (w.isUsable() && w.isArea() && ElemStyles.hasAreaElemStyle(w, false)) {
031                index.add(w);
032            }
033        }
034    
035        @Override
036        public void endTest() {
037            for (final Way w : index) {
038                Collection<Way> overlaps = Utils.filter(
039                        index.search(w.getBBox()),
040                        new Predicate<Way>() {
041    
042                            @Override
043                            public boolean evaluate(Way wi) {
044                                if (w.equals(wi))
045                                    return false;
046                                else
047                                    return Geometry.polygonIntersection(w.getNodes(), wi.getNodes())
048                                            == Geometry.PolygonIntersection.CROSSING;
049                            }
050                        });
051                if (!overlaps.isEmpty()) {
052                    Collection<Way> overlapsWater = new ArrayList<Way>();
053                    Collection<Way> overlapsOther = new ArrayList<Way>();
054    
055                    String natural1 = w.get("natural");
056                    String landuse1 = w.get("landuse");
057                    boolean isWaterArea = "water".equals(natural1) || "wetland".equals(natural1) || "coastline".equals(natural1) || "reservoir".equals(landuse1);
058                    boolean isWaterArea2 = false;
059    
060                    for (Way wayOther : overlaps) {
061                        String natural2 = wayOther.get("natural");
062                        String landuse2 = wayOther.get("landuse");
063                        boolean isWaterAreaTest = "water".equals(natural2) || "wetland".equals(natural2) || "coastline".equals(natural2) || "reservoir".equals(landuse2);
064    
065                        if (!isWaterArea2) {
066                            isWaterArea2 = isWaterAreaTest;
067                        }
068    
069                        if (isWaterArea && isWaterAreaTest) {
070                            overlapsWater.add(wayOther);
071                        } else {
072                            overlapsOther.add(wayOther);
073                        }
074                    }
075    
076                    if (!overlapsWater.isEmpty()) {
077                        errors.add(new TestError(this, Severity.WARNING, tr("Overlapping Water Areas"),
078                                OVERLAPPING_AREAS, Collections.singletonList(w), overlapsWater));
079                    }
080    
081                    if (!overlapsOther.isEmpty()) {
082                        errors.add(new TestError(this, Severity.OTHER, tr("Overlapping Areas"),
083                                OVERLAPPING_AREAS, Collections.singletonList(w), overlapsOther));
084                    }
085                }
086            }
087    
088            super.endTest();
089        }
090    
091    }