Search in sources :

Example 16 with Way

use of uk.me.parabola.mkgmap.reader.osm.Way in project mkgmap by openstreetmap.

the class BoundaryRelation method processElements.

/**
 * Process the ways in this relation. Joins way with the role "outer" Adds
 * ways with the role "inner" to the way with the role "outer"
 */
public void processElements() {
    log.info("Processing multipolygon", toBrowseURL());
    List<Way> allWays = getSourceWays();
    // join all single ways to polygons, try to close ways and remove non closed ways
    polygons = joinWays(allWays);
    outerWaysForLineTagging = new HashSet<>();
    outerTags = new HashMap<>();
    removeOutOfBbox(polygons);
    do {
        closeWays(polygons, getMaxCloseDist());
    } while (connectUnclosedWays(polygons));
    removeUnclosedWays(polygons);
    // now only closed ways are left => polygons only
    // check if we have at least one polygon left
    boolean hasPolygons = !polygons.isEmpty();
    removeWaysOutsideBbox(polygons);
    if (polygons.isEmpty()) {
        // do nothing
        if (log.isInfoEnabled()) {
            if (hasPolygons)
                log.info("Multipolygon", toBrowseURL(), "is completely outside the bounding box. It is not processed.");
            else
                log.info("Multipolygon " + toBrowseURL() + " does not contain a closed polygon.");
        }
        tagOuterWays();
        cleanup();
        return;
    }
    // the intersectingPolygons marks all intersecting/overlapping polygons
    intersectingPolygons = new HashSet<>();
    // check which polygons lie inside which other polygon
    createContainsMatrix(polygons);
    // unfinishedPolygons marks which polygons are not yet processed
    unfinishedPolygons = new BitSet(polygons.size());
    unfinishedPolygons.set(0, polygons.size());
    // create bitsets which polygons belong to the outer and to the inner role
    innerPolygons = new BitSet();
    taggedInnerPolygons = new BitSet();
    outerPolygons = new BitSet();
    taggedOuterPolygons = new BitSet();
    int wi = 0;
    for (Way w : polygons) {
        String role = getRole(w);
        if ("inner".equals(role)) {
            innerPolygons.set(wi);
            taggedInnerPolygons.set(wi);
        } else if ("outer".equals(role)) {
            outerPolygons.set(wi);
            taggedOuterPolygons.set(wi);
        } else {
            // unknown role => it could be both
            innerPolygons.set(wi);
            outerPolygons.set(wi);
        }
        wi++;
    }
    if (outerPolygons.isEmpty()) {
        log.warn("Multipolygon", toBrowseURL(), "does not contain any way tagged with role=outer or empty role.");
        cleanup();
        return;
    }
    Queue<PolygonStatus> polygonWorkingQueue = new LinkedBlockingQueue<PolygonStatus>();
    BitSet nestedOuterPolygons = new BitSet();
    BitSet nestedInnerPolygons = new BitSet();
    BitSet outmostPolygons;
    BitSet outmostInnerPolygons = new BitSet();
    boolean outmostInnerFound;
    do {
        outmostInnerFound = false;
        outmostPolygons = findOutmostPolygons(unfinishedPolygons);
        if (outmostPolygons.intersects(taggedInnerPolygons)) {
            outmostInnerPolygons.or(outmostPolygons);
            outmostInnerPolygons.and(taggedInnerPolygons);
            if (log.isDebugEnabled())
                log.debug("wrong inner polygons: " + outmostInnerPolygons);
            // do not process polygons tagged with role=inner but which are
            // not contained by any other polygon
            unfinishedPolygons.andNot(outmostInnerPolygons);
            outmostPolygons.andNot(outmostInnerPolygons);
            outmostInnerFound = true;
        }
    } while (outmostInnerFound);
    if (!outmostPolygons.isEmpty()) {
        polygonWorkingQueue.addAll(getPolygonStatus(outmostPolygons, "outer"));
    }
    boolean outmostPolygonProcessing = true;
    outerResultArea = new java.awt.geom.Area();
    while (!polygonWorkingQueue.isEmpty()) {
        // the polygon is not contained by any other unfinished polygon
        PolygonStatus currentPolygon = polygonWorkingQueue.poll();
        // this polygon is now processed and should not be used by any
        // further step
        unfinishedPolygons.clear(currentPolygon.index);
        BitSet polygonContains = new BitSet();
        polygonContains.or(containsMatrix.get(currentPolygon.index));
        // use only polygon that are contained by the polygon
        polygonContains.and(unfinishedPolygons);
        // polygonContains is the intersection of the unfinished and
        // the contained polygons
        // get the holes
        // these are all polygons that are in the main polygon
        // and that are not contained by any other polygon
        boolean holesOk;
        BitSet holeIndexes;
        do {
            holeIndexes = findOutmostPolygons(polygonContains);
            holesOk = true;
            if (currentPolygon.outer) {
                // for role=outer only role=inner is allowed
                if (holeIndexes.intersects(taggedOuterPolygons)) {
                    BitSet addOuterNestedPolygons = new BitSet();
                    addOuterNestedPolygons.or(holeIndexes);
                    addOuterNestedPolygons.and(taggedOuterPolygons);
                    nestedOuterPolygons.or(addOuterNestedPolygons);
                    holeIndexes.andNot(addOuterNestedPolygons);
                    // do not process them
                    unfinishedPolygons.andNot(addOuterNestedPolygons);
                    polygonContains.andNot(addOuterNestedPolygons);
                    // recalculate the holes again to get all inner polygons
                    // in the nested outer polygons
                    holesOk = false;
                }
            } else {
                // although inner in inner is not officially allowed
                if (holeIndexes.intersects(taggedInnerPolygons)) {
                    // process inner in inner but issue a warning later
                    BitSet addInnerNestedPolygons = new BitSet();
                    addInnerNestedPolygons.or(holeIndexes);
                    addInnerNestedPolygons.and(taggedInnerPolygons);
                    nestedInnerPolygons.or(addInnerNestedPolygons);
                }
            }
        } while (!holesOk);
        ArrayList<PolygonStatus> holes = getPolygonStatus(holeIndexes, (currentPolygon.outer ? "inner" : "outer"));
        // these polygons must all be checked for holes
        polygonWorkingQueue.addAll(holes);
        if (currentPolygon.outer) {
            // add the original ways to the list of ways that get the line tags of the mp
            // the joined ways may be changed by the auto closing algorithm
            outerWaysForLineTagging.addAll(currentPolygon.polygon.getOriginalWays());
        }
        if (currentPolygon.outer) {
            java.awt.geom.Area toAdd = Java2DConverter.createArea(currentPolygon.polygon.getPoints());
            if (outerResultArea.isEmpty())
                outerResultArea = toAdd;
            else
                outerResultArea.add(toAdd);
            for (Way outerWay : currentPolygon.polygon.getOriginalWays()) {
                if (outmostPolygonProcessing) {
                    for (Entry<String, String> tag : outerWay.getTagEntryIterator()) {
                        outerTags.put(tag.getKey(), tag.getValue());
                    }
                    outmostPolygonProcessing = false;
                } else {
                    for (String tag : new ArrayList<String>(outerTags.keySet())) {
                        if (outerTags.get(tag).equals(outerWay.getTag(tag)) == false) {
                            outerTags.remove(tag);
                        }
                    }
                }
            }
        } else {
            outerResultArea.subtract(Java2DConverter.createArea(currentPolygon.polygon.getPoints()));
        }
    }
    if (hasStyleRelevantTags(this)) {
        outerTags.clear();
        for (Entry<String, String> mpTags : getTagEntryIterator()) {
            if ("type".equals(mpTags.getKey()) == false) {
                outerTags.put(mpTags.getKey(), mpTags.getValue());
            }
        }
    } else {
        for (Entry<String, String> mpTags : outerTags.entrySet()) {
            addTag(mpTags.getKey(), mpTags.getValue());
        }
    }
    // the simple line information should be used.
    for (Way orgOuterWay : outerWaysForLineTagging) {
        // lineTagWay.addTag(STYLE_FILTER_TAG, STYLE_FILTER_LINE);
        for (Entry<String, String> tag : outerTags.entrySet()) {
            // remove the tag from the original way if it has the same value
            if (tag.getValue().equals(orgOuterWay.getTag(tag.getKey()))) {
                removeTagsInOrgWays(orgOuterWay, tag.getKey());
            }
        }
    // if (log.isDebugEnabled())
    // log.debug("Add line way", lineTagWay.getId(), lineTagWay.toTagString());
    // tileWayMap.put(lineTagWay.getId(), lineTagWay);
    }
    postProcessing();
    cleanup();
}
Also used : BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) Way(uk.me.parabola.mkgmap.reader.osm.Way)

Example 17 with Way

use of uk.me.parabola.mkgmap.reader.osm.Way in project mkgmap by openstreetmap.

the class PrecompSeaMerger method convertToWays.

private List<Way> convertToWays(Area a, String naturalTag) {
    List<List<Coord>> pointLists = Java2DConverter.areaToShapes(a);
    List<Way> ways = new ArrayList<Way>(pointLists.size());
    for (List<Coord> points : pointLists) {
        Way w = new Way(FakeIdGenerator.makeFakeId(), points);
        w.addTag("natural", naturalTag);
        w.setClosedInOSM(true);
        ways.add(w);
    }
    return ways;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) Way(uk.me.parabola.mkgmap.reader.osm.Way)

Example 18 with Way

use of uk.me.parabola.mkgmap.reader.osm.Way in project mkgmap by openstreetmap.

the class RuleFileReaderTest method testComplexExpressions.

/**
 * Try out arithmetic comparisons and mixtures of 'and' and 'or'.
 */
@Test
public void testComplexExpressions() {
    String str = "a=b & (c=d | e=f) & x>10 [0x1]\n";
    RuleSet rs = makeRuleSet(str);
    Element el = new Way(1);
    el.addTag("a", "b");
    el.addTag("c", "d");
    el.addTag("x", "11");
    GType type = getFirstType(rs, el);
    assertNotNull(type);
    assertEquals("expression ok", 1, type.getType());
    // fails with x less than 10
    el.addTag("x", "9");
    type = getFirstType(rs, el);
    assertNull("x too low", type);
    // also fails with x equal to 10
    el.addTag("x", "10");
    type = getFirstType(rs, el);
    assertNull("x too low", type);
    // OK with x > 10
    el.addTag("x", "100");
    el.addTag("e", "f");
    type = getFirstType(rs, el);
    assertNotNull(type);
    assertEquals("c and e set", 1, type.getType());
    el.addTag("c", "");
    el.addTag("e", "");
    type = getFirstType(rs, el);
    assertNull("none of c and e set", type);
    el.addTag("e", "f");
    type = getFirstType(rs, el);
    assertNotNull(type);
    assertEquals("e is set to f", 1, type.getType());
}
Also used : TestUtils.makeRuleSet(func.lib.TestUtils.makeRuleSet) GType(uk.me.parabola.mkgmap.reader.osm.GType) Element(uk.me.parabola.mkgmap.reader.osm.Element) Way(uk.me.parabola.mkgmap.reader.osm.Way) Test(org.junit.Test)

Example 19 with Way

use of uk.me.parabola.mkgmap.reader.osm.Way in project mkgmap by openstreetmap.

the class RuleFileReaderTest method testValueTagValue.

@Test
public void testValueTagValue() {
    RuleSet rs = makeRuleSet("a=$b [0x5]");
    Way w = new Way(1);
    w.addTag("a", "2");
    w.addTag("b", "2");
    GType type = getFirstType(rs, w);
    assertNotNull(type);
    assertEquals(5, type.getType());
}
Also used : TestUtils.makeRuleSet(func.lib.TestUtils.makeRuleSet) GType(uk.me.parabola.mkgmap.reader.osm.GType) Way(uk.me.parabola.mkgmap.reader.osm.Way) Test(org.junit.Test)

Example 20 with Way

use of uk.me.parabola.mkgmap.reader.osm.Way in project mkgmap by openstreetmap.

the class RuleFileReaderTest method testLoad.

/**
 * Test of a file containing a number of different rules, with varying
 * formatting and including comments.
 */
@Test
public void testLoad() {
    RuleSet rs = makeRuleSet("highway=footway & type=rough [0x2 level 2]\n" + "highway=footway | highway = path\n" + "  [0x3]\n# comment here\n" + "foo=\nbar & bar=two [0x4]\n" + "highway=* & oneway=true [0x6 level 1]\n" + "");
    Element el = new Way(1);
    el.addTag("highway", "footway");
    GType type = getFirstType(rs, el);
    assertNotNull(type);
    assertEquals("plain footway", "[0x3 level 0]", type.toString());
    el.addTag("type", "rough");
    type = getFirstType(rs, el);
    assertNotNull(type);
    assertEquals("rough footway", "[0x2 level 2]", type.toString());
}
Also used : TestUtils.makeRuleSet(func.lib.TestUtils.makeRuleSet) GType(uk.me.parabola.mkgmap.reader.osm.GType) Element(uk.me.parabola.mkgmap.reader.osm.Element) Way(uk.me.parabola.mkgmap.reader.osm.Way) Test(org.junit.Test)

Aggregations

Way (uk.me.parabola.mkgmap.reader.osm.Way)142 Test (org.junit.Test)94 TestUtils.makeRuleSet (func.lib.TestUtils.makeRuleSet)70 GType (uk.me.parabola.mkgmap.reader.osm.GType)60 Element (uk.me.parabola.mkgmap.reader.osm.Element)48 Coord (uk.me.parabola.imgfmt.app.Coord)31 ArrayList (java.util.ArrayList)18 MapPoint (uk.me.parabola.mkgmap.general.MapPoint)12 MapExitPoint (uk.me.parabola.mkgmap.general.MapExitPoint)11 List (java.util.List)8 Node (uk.me.parabola.mkgmap.reader.osm.Node)8 HashMap (java.util.HashMap)7 IdentityHashMap (java.util.IdentityHashMap)6 Map (java.util.Map)6 StringStyleFileLoader (func.lib.StringStyleFileLoader)5 CoordNode (uk.me.parabola.imgfmt.app.CoordNode)5 Relation (uk.me.parabola.mkgmap.reader.osm.Relation)5 CoordPOI (uk.me.parabola.mkgmap.reader.osm.CoordPOI)4 RestrictionRelation (uk.me.parabola.mkgmap.reader.osm.RestrictionRelation)4 Long2ObjectOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap)3