diff --git a/src/org/oscim/generator/JobQueue.java b/src/org/oscim/generator/JobQueue.java index 9957a2a5..8e065675 100644 --- a/src/org/oscim/generator/JobQueue.java +++ b/src/org/oscim/generator/JobQueue.java @@ -17,8 +17,6 @@ package org.oscim.generator; import static org.oscim.generator.JobTile.STATE_LOADING; import static org.oscim.generator.JobTile.STATE_NONE; -import java.util.Arrays; - /** * A JobQueue keeps the list of pending jobs for a MapView and prioritizes them. */ @@ -71,8 +69,12 @@ public class JobQueue { if (mJobs == null) return null; - if (mCurrentJob == 0) - Arrays.sort(mJobs); + if (mCurrentJob == 0) { + //Arrays.sort(mJobs); + int len = mJobs.length; + if (len > 1) + TileDistanceSort.sort(mJobs, 0, len); + } //return mPriorityQueue.poll(); JobTile t = mJobs[mCurrentJob]; diff --git a/src/org/oscim/generator/JobTile.java b/src/org/oscim/generator/JobTile.java index 97a1edca..61a252d0 100644 --- a/src/org/oscim/generator/JobTile.java +++ b/src/org/oscim/generator/JobTile.java @@ -21,7 +21,7 @@ import android.util.Log; /** * @author Hannes Janetzek */ -public class JobTile extends Tile implements Comparable { +public class JobTile extends Tile { private final static String TAG = JobTile.class.getName(); public final static int STATE_NONE = 0; @@ -59,15 +59,4 @@ public class JobTile extends Tile implements Comparable { public JobTile(int tileX, int tileY, byte zoomLevel) { super(tileX, tileY, zoomLevel); } - - @Override - public int compareTo(JobTile o) { - if (this.distance < o.distance) { - return -1; - } - if (this.distance > o.distance) { - return 1; - } - return 0; - } } diff --git a/src/org/oscim/generator/TileDistanceSort.java b/src/org/oscim/generator/TileDistanceSort.java index d9aa3cf0..1b642540 100644 --- a/src/org/oscim/generator/TileDistanceSort.java +++ b/src/org/oscim/generator/TileDistanceSort.java @@ -1,5 +1,5 @@ /* - * Copyright 2010, 2011, 2012 mapsforge.org + * Copyright 2013 OpenScienceMap * * This program is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free Software @@ -14,19 +14,109 @@ */ package org.oscim.generator; -import java.util.Comparator; - /** - * - * + * based on ComparableTimSort: + * everything below is Copyright OpenJDK, Oracle */ -public class TileDistanceSort implements Comparator { - @Override - public int compare(JobTile tile1, JobTile tile2) { - if (tile1.distance == tile2.distance) +public class TileDistanceSort { + public static void sort(JobTile[] a, int lo, int hi) { + int nRemaining = hi - lo; + if (nRemaining < 2) { + return; + } + + int initRunLen = countRunAndMakeAscending(a, lo, hi); + binarySort(a, lo, hi, lo + initRunLen); + + } + + static int compareTo(JobTile a, JobTile b) { + if (a == null && b == null) return 0; - return tile1.distance > tile2.distance ? 1 : -1; + if (a == null) + return 1; + + if (b == null) + return -1; + + if (a.distance < b.distance) { + return -1; + } + if (a.distance > b.distance) { + return 1; + } + return 0; + } + + private static void binarySort(JobTile[] a, int lo, int hi, int start) + { + assert ((lo <= start) && (start <= hi)); + if (start == lo) + ++start; + for (; start < hi; ++start) + { + JobTile pivot = a[start]; + + int left = lo; + int right = start; + assert (left <= right); + + while (left < right) { + int mid = left + right >>> 1; + //if (pivot.compareTo(a[mid]) < 0) + if (compareTo(pivot, a[mid]) < 0) + right = mid; + else + left = mid + 1; + } + assert (left == right); + + int n = start - left; + + switch (n) + { + case 2: + a[(left + 2)] = a[(left + 1)]; + //$FALL-THROUGH$ + case 1: + a[(left + 1)] = a[left]; + break; + default: + System.arraycopy(a, left, a, left + 1, n); + } + a[left] = pivot; + } + } + + private static int countRunAndMakeAscending(JobTile[] a, int lo, int hi) + { + assert (lo < hi); + int runHi = lo + 1; + if (runHi == hi) { + return 1; + } + + if (compareTo((a[(runHi++)]), a[lo]) < 0) { + while ((runHi < hi) && (compareTo((a[runHi]), a[(runHi - 1)]) < 0)) + ++runHi; + reverseRange(a, lo, runHi); + } else { + while ((runHi < hi) && (compareTo((a[runHi]), a[(runHi - 1)]) >= 0)) { + ++runHi; + } + } + return (runHi - lo); + } + + private static void reverseRange(JobTile[] a, int lo, int hi) + { + --hi; + while (lo < hi) { + JobTile t = a[lo]; + a[(lo++)] = a[hi]; + a[(hi--)] = t; + } } } diff --git a/src/org/oscim/renderer/TileManager.java b/src/org/oscim/renderer/TileManager.java index 4ec39f4e..def04fbc 100644 --- a/src/org/oscim/renderer/TileManager.java +++ b/src/org/oscim/renderer/TileManager.java @@ -26,6 +26,7 @@ import java.util.Arrays; import org.oscim.core.MapPosition; import org.oscim.core.Tile; import org.oscim.generator.JobTile; +import org.oscim.generator.TileDistanceSort; import org.oscim.renderer.layer.TextItem; import org.oscim.renderer.layer.VertexPool; import org.oscim.view.MapView; @@ -471,10 +472,10 @@ public class TileManager { t.vbo = null; } - mTilesCount--; QuadTree.remove(t); - t.state = STATE_NONE; + + mTilesCount--; } private static void updateTileDistances(Object[] tiles, int size, MapPosition mapPosition) { @@ -536,58 +537,38 @@ public class TileManager { private static void limitCache(MapPosition mapPosition, int remove) { MapTile[] tiles = mTiles; + int size = mTilesSize; // remove tiles that were never loaded - for (int i = 0, size = mTilesSize; i < size; i++) { + for (int i = 0; i < size; i++) { MapTile t = tiles[i]; if (t == null) continue; // make sure tile cannot be used by GL or MapWorker Thread - if (t.isLocked() || t.isActive()) { + if ((t.state != 0) || t.isLocked()) { continue; } clearTile(t); tiles[i] = null; remove--; - size--; } - if (remove > 5) { - int size = mTilesSize; + if (remove > 10) { + updateTileDistances(tiles, size, mapPosition); - if (size > mTilesCount) { - Log.d(TAG, "repack: " + size + " " + mTilesCount); + // double start, end; + // start = SystemClock.uptimeMillis(); - int start = 0; - // get first position to shift - while (start < size && tiles[start] != null) - start++; - int space = start + 1; - for (int end = 0; end < size;) { - // get the number of slots to shift - while (space < size && tiles[space] == null) - space++; - // get the position of next free slots - end = space; - while (end < size && tiles[end] != null) - end++; - // number of items to shift - int len = end - space; + TileDistanceSort.sort(tiles, 0, size); - if (len > 0) { - System.arraycopy(tiles, space, tiles, start, len); - start = start + len; - space = end; - } - } - Log.d(TAG, "repacked tiles to: " + start); - Arrays.fill(mTiles, start, mTilesSize, null); - mTilesSize = size = start; - } + //end = SystemClock.uptimeMillis(); + //Log.d(TAG, "sort took " + (end - start) + + // "limitCache: repacked: " + mTilesSize + " to: " + mTilesCount); - updateTileDistances(mTiles, size, mapPosition); - Arrays.sort(mTiles, 0, size); + // sorting also repacks the 'sparse' filled array + // so end of mTiles is at mTilesCount now + mTilesSize = size = mTilesCount; for (int i = 1; i < remove; i++) { MapTile t = tiles[size - i];