Index: src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 17654)
+++ src/org/openstreetmap/josm/data/osm/DataSet.java	(working copy)
@@ -61,6 +61,7 @@
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ListenerList;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Stopwatch;
 import org.openstreetmap.josm.tools.SubclassFilteredCollection;
 
 /**
@@ -191,6 +192,7 @@
         // Transparently register as projection change listener. No need to explicitly remove
         // the listener, projection change listeners are managed as WeakReferences.
         ProjectionRegistry.addProjectionChangeListener(this);
+        spatialIndexFilled = false;
     }
 
     /**
@@ -359,6 +361,8 @@
      */
     private final Map<String, String> changeSetTags = new HashMap<>();
 
+    private boolean spatialIndexFilled;
+
     /**
      * Replies the set of changeset tags to be applied when or if this is ever uploaded.
      * @return the set of changeset tags
@@ -392,6 +396,7 @@
     public List<Node> searchNodes(BBox bbox) {
         lock.readLock().lock();
         try {
+            assertIndexFilled();
             return store.searchNodes(bbox);
         } finally {
             lock.readLock().unlock();
@@ -407,6 +412,7 @@
     public List<Way> searchWays(BBox bbox) {
         lock.readLock().lock();
         try {
+            assertIndexFilled();
             return store.searchWays(bbox);
         } finally {
             lock.readLock().unlock();
@@ -417,6 +423,7 @@
     public List<Relation> searchRelations(BBox bbox) {
         lock.readLock().lock();
         try {
+            assertIndexFilled();
             return store.searchRelations(bbox);
         } finally {
             lock.readLock().unlock();
@@ -423,6 +430,18 @@
         }
     }
 
+    private void assertIndexFilled() {
+        if (!spatialIndexFilled) {
+            Stopwatch stopwatch = Stopwatch.createStarted();
+            allPrimitives.forEach(p -> {
+                p.updatePosition();
+                store.addPrimitive(p);
+            });
+            spatialIndexFilled = true;
+            Logging.info(stopwatch.toString("Creation of spatial index for " + allPrimitives.size() + " objects"));
+        }
+    }
+
     /**
      * Searches for all primitives in the given bounding box
      *
@@ -453,6 +472,7 @@
      */
     @Override
     public boolean containsNode(Node n) {
+        assertIndexFilled();
         return store.containsNode(n);
     }
 
@@ -466,6 +486,7 @@
      */
     @Override
     public boolean containsWay(Way w) {
+        assertIndexFilled();
         return store.containsWay(w);
     }
 
@@ -479,6 +500,7 @@
      */
     @Override
     public boolean containsRelation(Relation r) {
+        assertIndexFilled();
         return store.containsRelation(r);
     }
 
@@ -500,8 +522,10 @@
 
             allPrimitives.add(primitive);
             primitive.setDataset(this);
-            primitive.updatePosition(); // Set cached bbox for way and relation (required for reindexWay and reindexRelation to work properly)
-            store.addPrimitive(primitive);
+            if (spatialIndexFilled) {
+                primitive.updatePosition(); // Set cached bbox for way and relation (required for reindexWay and reindexRelation to work properly)
+                store.addPrimitive(primitive);
+            }
             firePrimitivesAdded(Collections.singletonList(primitive), false);
         });
     }
@@ -532,7 +556,9 @@
         if (primitive.isSelected()) {
             throw new DataIntegrityProblemException("Primitive was re-selected by a selection listener: " + primitive);
         }
-        store.removePrimitive(primitive);
+        if (spatialIndexFilled) {
+            store.removePrimitive(primitive);
+        }
         allPrimitives.remove(primitive);
         primitive.setDataset(null);
     }
@@ -1025,17 +1051,23 @@
     }
 
     void fireRelationMembersChanged(Relation r) {
-        store.reindexRelation(r, Relation::updatePosition);
+        if (spatialIndexFilled) {
+            store.reindexRelation(r, Relation::updatePosition);
+        }
         fireEvent(new RelationMembersChangedEvent(this, r));
     }
 
     void fireNodeMoved(Node node, LatLon newCoor, EastNorth eastNorth) {
-        store.reindexNode(node, n -> n.setCoorInternal(newCoor, eastNorth), Way::updatePosition, Relation::updatePosition);
+        if (spatialIndexFilled) {
+            store.reindexNode(node, n -> n.setCoorInternal(newCoor, eastNorth), Way::updatePosition, Relation::updatePosition);
+        } else {
+            node.setCoorInternal(newCoor, eastNorth);
+        }
         fireEvent(new NodeMovedEvent(this, node));
     }
 
     void fireWayNodesChanged(Way way) {
-        if (!way.isEmpty()) {
+        if (spatialIndexFilled && !way.isEmpty() ) {
             store.reindexWay(way, Way::updatePosition, Relation::updatePosition);
         }
         fireEvent(new WayNodesChangedEvent(this, way));
