Changeset 7145 in josm for trunk


Ignore:
Timestamp:
2014-05-19T18:03:52+02:00 (11 years ago)
Author:
simon04
Message:

see #10037 - Improve node-inside-multipolygon matching by handling rings consisting of several ways correctly

Location:
trunk/src/org/openstreetmap/josm
Files:
2 edited

Legend:

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

    r7005 r7145  
    4848         * @return list of nodes
    4949         */
    50         private List<Node> getNodes() {
     50        public List<Node> getNodes() {
    5151            List<Node> nodes = new ArrayList<>();
    5252
     
    108108     * @return error description if the ways cannot be split, {@code null} if all fine.
    109109     */
    110     public String makeFromWays(Collection<Way> ways){
     110    public String makeFromWays(Collection<Way> ways) {
     111        try {
     112            List<JoinedPolygon> joinedWays = joinWays(ways);
     113            //analyze witch way is inside witch outside.
     114            return makeFromPolygons(joinedWays);
     115        } catch (JoinedPolygonCreationException ex) {
     116            return ex.getMessage();
     117        }
     118    }
     119
     120    /**
     121     * An exception indicating an error while joining ways to multipolygon rings.
     122     */
     123    public static class JoinedPolygonCreationException extends RuntimeException {
     124        public JoinedPolygonCreationException(String message) {
     125            super(message);
     126        }
     127    }
     128
     129    /**
     130     * Joins the given {@code ways} to multipolygon rings.
     131     * @param ways the ways to join.
     132     * @return a list of multipolygon rings.
     133     * @throws JoinedPolygonCreationException if the creation fails.
     134     */
     135    public static List<JoinedPolygon> joinWays(Collection<Way> ways) throws JoinedPolygonCreationException {
    111136        List<JoinedPolygon> joinedWays = new ArrayList<>();
    112137
     
    117142        for(Way w: ways) {
    118143            if (w.getNodesCount() < 2) {
    119                 return tr("Cannot add a way with only {0} nodes.", w.getNodesCount());
     144                throw new JoinedPolygonCreationException(tr("Cannot add a way with only {0} nodes.", w.getNodesCount()));
    120145            }
    121146
     
    162187
    163188                if (adjacentWays.size() != 2) {
    164                     return tr("Each node must connect exactly 2 ways");
     189                    throw new JoinedPolygonCreationException(tr("Each node must connect exactly 2 ways"));
    165190                }
    166191
     
    181206        }
    182207
    183         //analyze witch way is inside witch outside.
    184         return makeFromPolygons(joinedWays);
     208        return joinedWays;
    185209    }
    186210
  • trunk/src/org/openstreetmap/josm/tools/Geometry.java

    r7072 r7145  
    2424import org.openstreetmap.josm.data.coor.LatLon;
    2525import org.openstreetmap.josm.data.osm.BBox;
     26import org.openstreetmap.josm.data.osm.MultipolygonCreate;
    2627import org.openstreetmap.josm.data.osm.Node;
    2728import org.openstreetmap.josm.data.osm.NodePositionComparator;
     
    860861    public static boolean isPolygonInsideMultiPolygon(List<Node> nodes, Relation multiPolygon, Predicate<Way> isOuterWayAMatch) {
    861862        // Extract outer/inner members from multipolygon
    862         MultiPolygonMembers mpm = new MultiPolygonMembers(multiPolygon);
     863        final MultiPolygonMembers mpm = new MultiPolygonMembers(multiPolygon);
     864        // Construct complete rings for the inner/outer members
     865        final List<MultipolygonCreate.JoinedPolygon> outerRings;
     866        final List<MultipolygonCreate.JoinedPolygon> innerRings;
     867        try {
     868            outerRings = MultipolygonCreate.joinWays(mpm.outers);
     869            innerRings = MultipolygonCreate.joinWays(mpm.inners);
     870        } catch (MultipolygonCreate.JoinedPolygonCreationException ex) {
     871            Main.debug("Invalid multipolygon " + multiPolygon);
     872            return false;
     873        }
    863874        // Test if object is inside an outer member
    864         for (Way out : mpm.outers) {
     875        for (MultipolygonCreate.JoinedPolygon out : outerRings) {
    865876            if (nodes.size() == 1
    866877                    ? nodeInsidePolygon(nodes.get(0), out.getNodes())
     
    868879                boolean insideInner = false;
    869880                // If inside an outer, check it is not inside an inner
    870                 for (Way in : mpm.inners) {
     881                for (MultipolygonCreate.JoinedPolygon in : innerRings) {
    871882                    if (polygonIntersection(in.getNodes(), out.getNodes()) == PolygonIntersection.FIRST_INSIDE_SECOND
    872883                            && (nodes.size() == 1
     
    880891                if (!insideInner) {
    881892                    // Final check using predicate
    882                     if (isOuterWayAMatch == null || isOuterWayAMatch.evaluate(out)) {
     893                    if (isOuterWayAMatch == null || isOuterWayAMatch.evaluate(out.ways.get(0) /* TODO give a better representation of the outer ring to the predicate */)) {
    883894                        return true;
    884895                    }
Note: See TracChangeset for help on using the changeset viewer.