Ticket #13361: 13361_v3.patch

File 13361_v3.patch, 26.6 KB (added by GerdP, 3 years ago)
  • src/org/openstreetmap/josm/data/osm/BBox.java

     
    99import org.openstreetmap.josm.data.coor.QuadTiling;
    1010import org.openstreetmap.josm.tools.Utils;
    1111
     12/**
     13 * A bounding box with latitude  / longitude coordinates
     14 */
    1215public class BBox {
     16    private double xmin;
     17    private double xmax;
     18    private double ymin;
     19    private double ymax;
    1320
    14     private double xmin = Double.POSITIVE_INFINITY;
    15     private double xmax = Double.NEGATIVE_INFINITY;
    16     private double ymin = Double.POSITIVE_INFINITY;
    17     private double ymax = Double.NEGATIVE_INFINITY;
     21    /**
     22     * Constructs a new (invalid) BBox
     23     */
     24    public BBox() {
     25        setInvalid();
     26    }
    1827
    1928    /**
    2029     * Constructs a new {@code BBox} defined by a single point.
     
    2433     * @since 6203
    2534     */
    2635    public BBox(final double x, final double y) {
    27         xmax = xmin = x;
    28         ymax = ymin = y;
    29         sanity();
     36        if (Double.isNaN(x) || Double.isNaN(y)) {
     37            setInvalid();
     38        } else {
     39            xmin = x;
     40            ymin = y;
     41            xmax = x;
     42            ymax = y;
     43            sanity();
     44        }
    3045    }
    3146
    3247    /**
    3348     * Constructs a new {@code BBox} defined by points <code>a</code> and <code>b</code>.
    34      * Result is minimal BBox containing both points.
     49     * Result is minimal BBox containing both points if they are both valid, else undefined
    3550     *
    3651     * @param a first point
    3752     * @param b second point
     
    5267        this.ymax = copy.ymax;
    5368    }
    5469
     70    /**
     71     * Create minimal  BBox so that {@code this.bounds(ax,ay)} and {@code this.bounds(bx,by)} will both return true
     72     * @param ax left or right X value (-180 .. 180)
     73     * @param ay top or bottom Y value (-90 .. 90)
     74     * @param bx left or right X value (-180 .. 180)
     75     * @param by top or bottom Y value (-90 .. 90)
     76     */
    5577    public BBox(double ax, double ay, double bx, double by) {
     78        if (Double.isNaN(ax) || Double.isNaN(ay) || Double.isNaN(bx) || Double.isNaN(by)) {
     79            setInvalid();
     80            return; // use default which is an invalid BBox
     81        }
    5682
    5783        if (ax > bx) {
    5884            xmax = ax;
     
    6995            ymax = by;
    7096            ymin = ay;
    7197        }
    72 
    7398        sanity();
    7499    }
    75100
     101    /**
     102     * Create BBox for all nodes of the way with known coordinates.
     103     * If no node has a known coordinate, an invalid BBox is returned.
     104     * @param w the way
     105     */
    76106    public BBox(Way w) {
    77         for (Node n : w.getNodes()) {
    78             LatLon coor = n.getCoor();
    79             if (coor == null) {
    80                 continue;
    81             }
    82             add(coor);
    83         }
     107        setInvalid();
     108        w.getNodes().forEach((n) -> add(n.getCoor()));
    84109    }
    85110
     111    /**
     112     * Create BBox for a node. An invalid BBox is returned if the coordinates are not known.
     113     * @param n the node
     114     */
    86115    public BBox(Node n) {
    87         LatLon coor = n.getCoor();
    88         if (coor == null) {
    89             xmin = xmax = ymin = ymax = 0;
    90         } else {
    91             xmin = xmax = coor.lon();
    92             ymin = ymax = coor.lat();
    93         }
     116        if (n.isLatLonKnown())
     117            add(n.getCoor());
     118        else
     119            setInvalid();
    94120    }
    95121
     122    private void setInvalid() {
     123        xmin = Double.POSITIVE_INFINITY;
     124        xmax = Double.NEGATIVE_INFINITY;
     125        ymin = Double.POSITIVE_INFINITY;
     126        ymax = Double.NEGATIVE_INFINITY;
     127    }
     128
    96129    private void sanity() {
    97130        if (xmin < -180.0) {
    98131            xmin = -180.0;
     
    108141        }
    109142    }
    110143
     144    /**
     145     * Add a point to an existing BBox. Extends this bbox if necessary so that this.bounds(c) will return true
     146     * if c is a valid LatLon instance.
     147     * @param c a LatLon point
     148     */
    111149    public final void add(LatLon c) {
    112         add(c.lon(), c.lat());
     150        if (c != null && c.isValid())
     151            add(c.lon(), c.lat());
    113152    }
    114153
    115154    /**
     
    118157     * @param y Y coordinate
    119158     */
    120159    public final void add(double x, double y) {
     160        if (Double.isNaN(x) || Double.isNaN(y))
     161            return;
    121162        xmin = Math.min(xmin, x);
    122163        xmax = Math.max(xmax, x);
    123164        ymin = Math.min(ymin, y);
     
    125166        sanity();
    126167    }
    127168
    128     public final void add(BBox box) {
    129         xmin = Math.min(xmin, box.xmin);
    130         xmax = Math.max(xmax, box.xmax);
    131         ymin = Math.min(ymin, box.ymin);
    132         ymax = Math.max(ymax, box.ymax);
    133         sanity();
     169    /**
     170     * Extends this bbox to include the bbox other. Does nothing if other is not valid.
     171     * @param other a bbox
     172     */
     173    public final void add(BBox other) {
     174        if (other.isValid()) {
     175            xmin = Math.min(xmin, other.xmin);
     176            xmax = Math.max(xmax, other.xmax);
     177            ymin = Math.min(ymin, other.ymin);
     178            ymax = Math.max(ymax, other.ymax);
     179            sanity();
     180        }
    134181    }
    135182
     183    /**
     184     * Extends this bbox to include the bbox of the primitive extended by extraSpace.
     185     * @param primitive an OSM primitive
     186     * @param extraSpace the value to extend the primitives bbox. Unit is in LatLon degrees.
     187     */
    136188    public void addPrimitive(OsmPrimitive primitive, double extraSpace) {
    137189        BBox primBbox = primitive.getBBox();
    138190        add(primBbox.xmin - extraSpace, primBbox.ymin - extraSpace);
     
    278330            && Double.compare(b.xmin, xmin) == 0 && Double.compare(b.ymin, ymin) == 0;
    279331    }
    280332
     333    /**
     334     * @return true if the bbox covers a part of the planets surface
     335     * Height and width must be non-negative, but may (both) be 0.
     336     */
     337    public boolean isValid() {
     338        return (xmin <= xmax && ymin <= ymax);
     339    }
     340
     341    /**
     342     * @return true if the bbox covers a part of the planets surface
     343     */
     344    public boolean isInWorld() {
     345        return !(xmin < -180.0 || xmax > 180.0 || ymin < -90.0 || ymax > 90.0);
     346    }
     347
    281348    @Override
    282349    public String toString() {
    283350        return "[ x: " + xmin + " -> " + xmax + ", y: " + ymin + " -> " + ymax + " ]";
  • src/org/openstreetmap/josm/data/osm/DataSet.java

     
    508508                throw new DataIntegrityProblemException(
    509509                        tr("Unable to add primitive {0} to the dataset because it is already included", primitive.toString()));
    510510
    511             primitive.updatePosition(); // Set cached bbox for way and relation (required for reindexWay and reinexRelation to work properly)
     511            allPrimitives.add(primitive);
     512            primitive.setDataset(this);
     513            primitive.updatePosition(); // Set cached bbox for way and relation (required for reindexWay and reindexRelation to work properly)
    512514            boolean success = false;
    513515            if (primitive instanceof Node) {
    514516                success = nodes.add((Node) primitive);
     
    519521            }
    520522            if (!success)
    521523                throw new RuntimeException("failed to add primitive: "+primitive);
    522             allPrimitives.add(primitive);
    523             primitive.setDataset(this);
    524524            firePrimitivesAdded(Collections.singletonList(primitive), false);
    525525        } finally {
    526526            endUpdate();
  • src/org/openstreetmap/josm/data/osm/Node.java

     
    325325
    326326    @Override
    327327    public BBox getBBox() {
    328         return new BBox(this);
     328        return new BBox(lon, lat);
    329329    }
    330330
    331331    @Override
     332    protected void addToBBox(BBox box, Set<PrimitiveId> visited) {
     333        box.add(lon, lat);
     334    }
     335
     336    @Override
    332337    public void updatePosition() {
    333338        // Do nothing
    334339    }
     
    408413        return !isNewOrUndeleted() && getDataSet() != null && getDataSet().getDataSourceArea() != null
    409414                && getCoor() != null && !getCoor().isIn(getDataSet().getDataSourceArea());
    410415    }
     416
    411417}
  • src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

     
    14811481    public boolean isMultipolygon() {
    14821482        return false;
    14831483    }
     1484
     1485    /**
     1486     * If necessary, extend the bbox to contain this primitive
     1487     * @param box a bbox instance
     1488     * @param visited a set of visited members  or null
     1489     */
     1490    protected abstract void addToBBox(BBox box, Set<PrimitiveId> visited);
    14841491}
  • src/org/openstreetmap/josm/data/osm/QuadBuckets.java

     
    55import java.util.Arrays;
    66import java.util.Collection;
    77import java.util.Iterator;
     8import java.util.LinkedHashSet;
    89import java.util.List;
    910import java.util.NoSuchElementException;
    1011
     
    3132        throw new AssertionError(s);
    3233    }
    3334
    34     public static final int MAX_OBJECTS_PER_LEVEL = 16;
     35    private static final int MAX_OBJECTS_PER_LEVEL = 16;
    3536
    3637    static class QBLevel<T extends OsmPrimitive> {
    3738        private final int level;
     
    181182        }
    182183
    183184        boolean matches(final T o, final BBox searchBbox) {
    184             if (o instanceof Node) {
    185                 final LatLon latLon = ((Node) o).getCoor();
    186                 // node without coords -> bbox[0,0,0,0]
    187                 return searchBbox.bounds(latLon != null ? latLon : LatLon.ZERO);
    188             }
    189185            return o.getBBox().intersects(searchBbox);
    190186        }
    191187
     
    393389    private QBLevel<T> root;
    394390    private QBLevel<T> searchCache;
    395391    private int size;
     392    private Collection<T> invalidBBoxPrimitives;
    396393
    397394    /**
    398395     * Constructs a new {@code QuadBuckets}.
     
    404401    @Override
    405402    public final void clear() {
    406403        root = new QBLevel<>(this);
     404        invalidBBoxPrimitives = new LinkedHashSet<>();
    407405        searchCache = null;
    408406        size = 0;
    409407    }
     
    410408
    411409    @Override
    412410    public boolean add(T n) {
    413         root.add(n);
     411        if (n.getBBox().isValid())
     412            root.add(n);
     413        else
     414            invalidBBoxPrimitives.add(n);
    414415        size++;
    415416        return true;
    416417    }
     
    460461        T t = (T) o;
    461462        searchCache = null; // Search cache might point to one of removed buckets
    462463        QBLevel<T> bucket = root.findBucket(t.getBBox());
    463         if (bucket.removeContent(t)) {
     464        boolean removed = bucket.removeContent(t);
     465        if (!removed)
     466            removed = invalidBBoxPrimitives.remove(o);
     467        if (removed)
    464468            size--;
    465             return true;
    466         } else
    467             return false;
     469        return removed;
    468470    }
    469471
    470472    @Override
     
    471473    public boolean contains(Object o) {
    472474        @SuppressWarnings("unchecked")
    473475        T t = (T) o;
     476        if (!t.getBBox().isValid())
     477            return invalidBBoxPrimitives.contains(o);
    474478        QBLevel<T> bucket = root.findBucket(t.getBBox());
    475479        return bucket != null && bucket.content != null && bucket.content.contains(t);
    476480    }
     
    501505        private QBLevel<T> currentNode;
    502506        private int contentIndex;
    503507        private int iteratedOver;
     508        private Iterator<T> invalidBBoxIterator = invalidBBoxPrimitives.iterator();
     509        boolean fromInvalidBBoxPrimitives;
    504510        QuadBuckets<T> qb;
    505511
    506512        final QBLevel<T> nextContentNode(QBLevel<T> q) {
     
    527533
    528534        @Override
    529535        public boolean hasNext() {
    530             if (this.peek() == null)
    531                 return false;
     536            if (this.peek() == null) {
     537                fromInvalidBBoxPrimitives = true;
     538                return invalidBBoxIterator.hasNext();
     539            }
    532540            return true;
    533541        }
    534542
     
    549557
    550558        @Override
    551559        public T next() {
     560            if (fromInvalidBBoxPrimitives)
     561                return invalidBBoxIterator.next();
    552562            T ret = peek();
    553563            if (ret == null)
    554564                throw new NoSuchElementException();
     
    559569
    560570        @Override
    561571        public void remove() {
    562             // two uses
    563             // 1. Back up to the thing we just returned
    564             // 2. move the index back since we removed
    565             //    an element
    566             contentIndex--;
    567             T object = peek();
    568             if (currentNode.removeContent(object))
     572            if (fromInvalidBBoxPrimitives) {
     573                invalidBBoxIterator.remove();
    569574                qb.size--;
     575            } else {
     576                // two uses
     577                // 1. Back up to the thing we just returned
     578                // 2. move the index back since we removed
     579                //    an element
     580                contentIndex--;
     581                T object = peek();
     582                if (currentNode.removeContent(object))
     583                    qb.size--;
     584
     585            }
    570586        }
    571587    }
    572588
     
    585601        return size == 0;
    586602    }
    587603
     604    /**
     605     * Search for elements in the given bbox.
     606     * @param searchBbox the bbox
     607     * @return a list of elements, maybe empty but never null
     608     */
    588609    public List<T> search(BBox searchBbox) {
    589610        List<T> ret = new ArrayList<>();
     611        if (!searchBbox.isValid()) {
     612            return ret;
     613        }
    590614        // Doing this cuts down search cost on a real-life data set by about 25%
    591615        if (searchCache == null) {
    592616            searchCache = root;
  • src/org/openstreetmap/josm/data/osm/Relation.java

     
    427427
    428428    @Override
    429429    public BBox getBBox() {
    430         RelationMember[] members = this.members;
     430        if (getDataSet() != null && bbox != null)
     431            return new BBox(bbox); // use cached value
    431432
    432         if (members.length == 0)
    433             return new BBox(0, 0, 0, 0);
    434         if (getDataSet() == null)
    435             return calculateBBox(new HashSet<PrimitiveId>());
    436         else {
    437             if (bbox == null) {
    438                 bbox = calculateBBox(new HashSet<PrimitiveId>());
    439             }
    440             if (bbox == null)
    441                 return new BBox(0, 0, 0, 0); // No real members
    442             else
    443                 return new BBox(bbox);
    444         }
     433        BBox box = new BBox();
     434        addToBBox(box, new HashSet<PrimitiveId>());
     435        if (getDataSet() != null)
     436            bbox = box; // set cache
     437        return new BBox(box);
    445438    }
    446439
    447     private BBox calculateBBox(Set<PrimitiveId> visitedRelations) {
    448         if (visitedRelations.contains(this))
    449             return null;
    450         visitedRelations.add(this);
    451 
    452         RelationMember[] members = this.members;
    453         if (members.length == 0)
    454             return null;
    455         else {
    456             BBox result = null;
    457             for (RelationMember rm:members) {
    458                 BBox box = rm.isRelation() ? rm.getRelation().calculateBBox(visitedRelations) : rm.getMember().getBBox();
    459                 if (box != null) {
    460                     if (result == null) {
    461                         result = box;
    462                     } else {
    463                         result.add(box);
    464                     }
    465                 }
    466             }
    467             return result;
     440    @Override
     441    protected void addToBBox(BBox box, Set<PrimitiveId> visited) {
     442        for (RelationMember rm : members) {
     443            if (visited.add(rm.getMember()))
     444                rm.getMember().addToBBox(box, visited);
    468445        }
    469446    }
    470447
    471448    @Override
    472449    public void updatePosition() {
    473         bbox = calculateBBox(new HashSet<PrimitiveId>());
     450        bbox = null; // make sure that it is recalculated
     451        bbox = getBBox();
    474452    }
    475453
    476454    @Override
  • src/org/openstreetmap/josm/data/osm/Way.java

     
    633633    }
    634634
    635635    @Override
     636    protected void addToBBox(BBox box, Set<PrimitiveId> visited) {
     637        box.add(getBBox());
     638    }
     639
     640    @Override
    636641    public void updatePosition() {
    637642        bbox = new BBox(this);
    638643    }
  • test/unit/org/openstreetmap/josm/data/osm/BBoxTest.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.osm;
    33
     4import static org.junit.Assert.assertFalse;
     5import static org.junit.Assert.assertTrue;
     6
    47import org.junit.Before;
    58import org.junit.Test;
    69import org.openstreetmap.josm.JOSMFixture;
     10import org.openstreetmap.josm.data.coor.LatLon;
    711
    812import nl.jqno.equalsverifier.EqualsVerifier;
    913import nl.jqno.equalsverifier.Warning;
    10 
    1114/**
    1215 * Unit tests for class {@link BBox}.
    1316 */
     
    3033            .suppress(Warning.NONFINAL_FIELDS)
    3134            .verify();
    3235    }
     36
     37    @Test
     38    public void testLatLonConstructor() {
     39        LatLon latLon1 = new LatLon(10, 20);
     40        LatLon latLon2 = new LatLon(20, 10);
     41        BBox b1 = new BBox(latLon1, latLon2);
     42        BBox b2 = new BBox(latLon2, latLon1);
     43        assertTrue(b1.bounds(latLon1));
     44        assertTrue(b2.bounds(latLon1));
     45        assertTrue(b1.bounds(latLon2));
     46        assertTrue(b2.bounds(latLon2));
     47        assertTrue(b2.bounds(b1));
     48        assertTrue(b1.bounds(b2));
     49
     50        // invalid latlon values
     51        LatLon invalid1 = new LatLon(-190, 340);
     52        BBox b3 = new BBox(invalid1, latLon1);
     53        BBox b4 = new BBox(latLon1, invalid1);
     54        BBox b5 = new BBox(invalid1, invalid1);
     55        // what should be the result?
     56        assertTrue(b3.isValid());
     57        assertTrue(b4.isValid());
     58        assertTrue(b3.bounds(latLon1));
     59        assertTrue(b4.bounds(latLon1));
     60        assertFalse(b5.isValid());
     61    }
     62
    3363}
  • test/unit/org/openstreetmap/josm/data/osm/NodeTest.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.osm;
    33
     4import static org.junit.Assert.assertEquals;
    45import static org.junit.Assert.assertFalse;
    56import static org.junit.Assert.assertNotNull;
    67import static org.junit.Assert.assertNull;
     8import static org.junit.Assert.assertTrue;
    79
    810import org.junit.BeforeClass;
    911import org.junit.Test;
     
    4143        assertNull(n.getCoor());
    4244        assertFalse(n.isOutsideDownloadArea());
    4345    }
     46
     47    /**
     48     * Test BBox calculation with Node
     49     */
     50    @Test
     51    public void testBBox() {
     52        DataSet ds = new DataSet();
     53        Node n1 = new Node(1);
     54        Node n2 = new Node(2);
     55        Node n3 = new Node(3);
     56        Node n4 = new Node(4);
     57        n1.setIncomplete(true);
     58        n2.setCoor(new LatLon(10, 10));
     59        n3.setCoor(new LatLon(20, 20));
     60        n4.setCoor(new LatLon(90, 180));
     61        ds.addPrimitive(n1);
     62        ds.addPrimitive(n2);
     63        ds.addPrimitive(n3);
     64        ds.addPrimitive(n4);
     65
     66        assertFalse(n1.getBBox().isValid());
     67        assertTrue(n2.getBBox().isValid());
     68        assertTrue(n3.getBBox().isValid());
     69        assertTrue(n4.getBBox().isValid());
     70        BBox box1 = n1.getBBox();
     71        box1.add(n2.getCoor());
     72        assertTrue(box1.isValid());
     73        BBox box2 = n2.getBBox();
     74        box2.add(n1.getCoor());
     75        assertTrue(box2.isValid());
     76        assertEquals(box1, box2);
     77        box1.add(n3.getCoor());
     78        assertTrue(box1.isValid());
     79        assertEquals(box1.getCenter(), new LatLon(15, 15));
     80    }
    4481}
  • test/unit/org/openstreetmap/josm/data/osm/QuadBucketsTest.java

     
    88import java.util.Collection;
    99import java.util.Iterator;
    1010import java.util.List;
     11import java.util.Random;
    1112
    1213import org.fest.reflect.core.Reflection;
    1314import org.fest.reflect.reference.TypeRef;
     
    173174            Assert.assertEquals(count, qbWays.size());
    174175        }
    175176        Assert.assertEquals(0, qbWays.size());
     177
    176178    }
     179
     180    /**
     181     *  Add more data so that quad buckets tree has a few leaves
     182     */
     183    @Test
     184    public void testSplitsWithIncompleteData() {
     185        DataSet ds = new DataSet();
     186        long nodeId = 1;
     187        long wayId = 1;
     188        final int NUM_COMPLETE_WAYS = 300;
     189        final int NUM_INCOMPLETE_WAYS = 10;
     190        final int NUM_NODES_PER_WAY = 20;
     191        final int NUM_INCOMPLETE_NODES = 10;
     192
     193        // force splits in quad buckets
     194        Random random = new Random(31);
     195        for (int i = 0; i < NUM_COMPLETE_WAYS; i++) {
     196            Way w = new Way(wayId++);
     197            List<Node> nodes = new ArrayList<>();
     198            double center = random.nextDouble() * 10;
     199            for (int j = 0; j < NUM_NODES_PER_WAY; j++) {
     200                Node n = new Node(nodeId++);
     201                double lat = random.nextDouble() * 0.001;
     202                double lon = random.nextDouble() * 0.001;
     203                n.setCoor(new LatLon(center + lat, center + lon));
     204                nodes.add(n);
     205                ds.addPrimitive(n);
     206            }
     207            w.setNodes(nodes);
     208            ds.addPrimitive(w);
     209        }
     210        Assert.assertEquals(NUM_COMPLETE_WAYS, ds.getWays().size());
     211        Assert.assertEquals(NUM_COMPLETE_WAYS * NUM_NODES_PER_WAY, ds.getNodes().size());
     212
     213        // add some incomplete nodes
     214        List<Node> incompleteNodes = new ArrayList<>();
     215        for (int i = 0; i < NUM_INCOMPLETE_NODES; i++) {
     216            Node n = new Node(nodeId++);
     217            incompleteNodes.add(n);
     218            n.setIncomplete(true);
     219            ds.addPrimitive(n);
     220        }
     221        Assert.assertEquals(NUM_COMPLETE_WAYS * NUM_NODES_PER_WAY + NUM_INCOMPLETE_NODES, ds.getNodes().size());
     222        // add some incomplete ways
     223        List<Way> incompleteWays = new ArrayList<>();
     224        for (int i = 0; i < NUM_INCOMPLETE_WAYS; i++) {
     225            Way w = new Way(wayId++);
     226            incompleteWays.add(w);
     227            w.setIncomplete(true);
     228            ds.addPrimitive(w);
     229        }
     230        Assert.assertEquals(NUM_COMPLETE_WAYS + NUM_INCOMPLETE_WAYS, ds.getWays().size());
     231
     232        BBox planet = new BBox(-180, -90, 180, 90);
     233        // incomplete ways should not be found with search
     234        Assert.assertEquals(NUM_COMPLETE_WAYS, ds.searchWays(planet).size());
     235        // incomplete ways are only retrieved via iterator or object reference
     236        for (Way w : incompleteWays) {
     237            Assert.assertTrue(ds.getWays().contains(w));
     238        }
     239
     240        QuadBuckets<Way> qb = new QuadBuckets<>();
     241        qb.addAll(ds.getWays());
     242        int count = qb.size();
     243        Assert.assertEquals(count, ds.getWays().size());
     244        Iterator<Way> iter = qb.iterator();
     245        while (iter.hasNext()) {
     246            iter.next();
     247            iter.remove();
     248            count--;
     249            Assert.assertEquals(count, qb.size());
     250        }
     251        Assert.assertEquals(0, qb.size());
     252    }
    177253}
  • test/unit/org/openstreetmap/josm/data/osm/RelationTest.java

     
    7474        w1.addNode(n3);
    7575        Assert.assertEquals(w1.getBBox(), r1.getBBox());
    7676        Assert.assertEquals(w1.getBBox(), r2.getBBox());
     77
     78        // create incomplete node and add it to the relation, this must not change the bbox
     79        BBox oldBBox = r2.getBBox();
     80        Node n4 = new Node();
     81        n4.setIncomplete(true);
     82        ds.addPrimitive(n4);
     83        r2.addMember(new RelationMember("", n4));
     84
     85        Assert.assertEquals(oldBBox, r2.getBBox());
    7786    }
    7887
    7988    @Test
  • test/unit/org/openstreetmap/josm/data/osm/WayTest.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.osm;
     3
     4import static org.junit.Assert.assertEquals;
     5import static org.junit.Assert.assertFalse;
     6import static org.junit.Assert.assertTrue;
     7
     8import java.util.Arrays;
     9
     10import org.junit.BeforeClass;
     11import org.junit.Test;
     12import org.openstreetmap.josm.JOSMFixture;
     13import org.openstreetmap.josm.data.coor.LatLon;
     14
     15/**
     16 * Unit tests of the {@code Node} class.
     17 */
     18public class WayTest {
     19
     20    /**
     21     * Setup test.
     22     */
     23    @BeforeClass
     24    public static void setUpBeforeClass() {
     25        JOSMFixture.createUnitTestFixture().init();
     26    }
     27
     28    /**
     29     * Test BBox calculation with Way
     30     */
     31    @Test
     32    public void testBBox() {
     33        DataSet ds = new DataSet();
     34        Node n1 = new Node(1);
     35        Node n2 = new Node(2);
     36        Node n3 = new Node(3);
     37        Node n4 = new Node(4);
     38        n1.setIncomplete(true);
     39        n2.setCoor(new LatLon(10, 10));
     40        n3.setCoor(new LatLon(20, 20));
     41        n4.setCoor(new LatLon(90, 180));
     42        ds.addPrimitive(n1);
     43        ds.addPrimitive(n2);
     44        ds.addPrimitive(n3);
     45        ds.addPrimitive(n4);
     46        Way way = new Way(1);
     47        assertFalse(way.getBBox().isValid());
     48        way.setNodes(Arrays.asList(n1));
     49        assertFalse(way.getBBox().isValid());
     50        way.setNodes(Arrays.asList(n2));
     51        assertTrue(way.getBBox().isValid());
     52        way.setNodes(Arrays.asList(n1, n2));
     53        assertTrue(way.getBBox().isValid());
     54        assertEquals(way.getBBox(), new BBox(10, 10));
     55    }
     56}