diff --git a/DataExtractionOSM/.classpath b/DataExtractionOSM/.classpath
index ff1c24c60c..8d48231432 100644
--- a/DataExtractionOSM/.classpath
+++ b/DataExtractionOSM/.classpath
@@ -5,5 +5,6 @@
+
diff --git a/DataExtractionOSM/lib/sqlitejdbc-v056.jar b/DataExtractionOSM/lib/sqlitejdbc-v056.jar
new file mode 100644
index 0000000000..f95d90eb07
Binary files /dev/null and b/DataExtractionOSM/lib/sqlitejdbc-v056.jar differ
diff --git a/DataExtractionOSM/src/com/osmand/data/preparation/DataIndexBuilder.java b/DataExtractionOSM/src/com/osmand/data/preparation/DataIndexBuilder.java
index 8e5c198f56..b690ec96ab 100644
--- a/DataExtractionOSM/src/com/osmand/data/preparation/DataIndexBuilder.java
+++ b/DataExtractionOSM/src/com/osmand/data/preparation/DataIndexBuilder.java
@@ -4,6 +4,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
@@ -59,7 +60,7 @@ public class DataIndexBuilder {
}
- public DataIndexBuilder buildPOI() throws XMLStreamException, IOException {
+ public DataIndexBuilder buildPOI() throws XMLStreamException, IOException, SQLException {
List list = region.getAmenityManager().getAllObjects();
List interestedObjects = new ArrayList(list.size());
@@ -75,6 +76,8 @@ public class DataIndexBuilder {
}
OsmStorageWriter writer = new OsmStorageWriter();
writer.saveLuceneIndex(new File(workingDir, "lucene"), region);
+ writer.saveSQLLitePOIIndex(new File(workingDir, "POI/"+region.getName()+".db"), region);
+
return this;
}
diff --git a/DataExtractionOSM/src/com/osmand/osm/io/OsmStorageWriter.java b/DataExtractionOSM/src/com/osmand/osm/io/OsmStorageWriter.java
index b616066797..c3d6c1e52a 100644
--- a/DataExtractionOSM/src/com/osmand/osm/io/OsmStorageWriter.java
+++ b/DataExtractionOSM/src/com/osmand/osm/io/OsmStorageWriter.java
@@ -29,6 +29,11 @@ import static com.osmand.osm.io.OsmIndexStorage.OSMAND_VERSION;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -212,11 +217,56 @@ public class OsmStorageWriter {
//for (Entry entry:amenity.getNode().getTags().entrySet()) {
// document.add(new Field(entry.getKey(),entry.getValue(),Store.YES, Index.NOT_ANALYZED));
//}
-
writer.addDocument(document);
}
+ public void saveSQLLitePOIIndex(File file, Region region) throws SQLException{
+ long now = System.currentTimeMillis();
+ try {
+ Class.forName("org.sqlite.JDBC");
+ } catch (ClassNotFoundException e) {
+ log.error("Illegal configuration", e);
+ throw new IllegalStateException(e);
+ }
+ Connection conn = DriverManager.getConnection("jdbc:sqlite:"+file.getAbsolutePath());
+
+ final int batchSize = 500;
+ try {
+ Statement stat = conn.createStatement();
+ stat.executeUpdate("create table poi (id long, latitude double, longitude double, name, type, subtype);");
+ stat.executeUpdate("create index LatLonIndex ON poi (latitude, longitude);");
+ PreparedStatement prep = conn.prepareStatement(
+ "insert into poi values (?, ?, ?, ?, ? ,? );");
+ conn.setAutoCommit(false);
+ int currentCount = 0;
+ for (Amenity a : region.getAmenityManager().getAllObjects()) {
+ prep.setLong(1, a.getId());
+ prep.setDouble(2, a.getLocation().getLatitude());
+ prep.setDouble(3, a.getLocation().getLongitude());
+ prep.setString(4, a.getName());
+ prep.setString(5, AmenityType.valueToString(a.getType()));
+ prep.setString(6, a.getSubType());
+ prep.addBatch();
+ currentCount++;
+ if(currentCount >= batchSize){
+ prep.executeBatch();
+ currentCount = 0;
+ }
+
+ }
+ if(currentCount > 0){
+ prep.executeBatch();
+ }
+ conn.setAutoCommit(true);
+ } finally {
+ conn.close();
+ log.info(String.format("Indexing sqllite done in %s ms.", System.currentTimeMillis() - now));
+ }
+
+ }
+
+
public void savePOIIndex(OutputStream output, Region region) throws XMLStreamException, IOException {
PropertyManager propertyManager = new PropertyManager(PropertyManager.CONTEXT_WRITER);
XMLStreamWriter streamWriter = new XMLStreamWriterImpl(output, propertyManager);
diff --git a/DataExtractionOSM/src/com/osmand/swing/OsmExtractionUI.java b/DataExtractionOSM/src/com/osmand/swing/OsmExtractionUI.java
index 1bf605c3aa..14d7fbb101 100644
--- a/DataExtractionOSM/src/com/osmand/swing/OsmExtractionUI.java
+++ b/DataExtractionOSM/src/com/osmand/swing/OsmExtractionUI.java
@@ -13,6 +13,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
+import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -372,6 +373,8 @@ public class OsmExtractionUI implements IMapLocationListener {
JOptionPane pane = new JOptionPane(msg);
JDialog dialog = pane.createDialog(frame, "Generation data");
dialog.setVisible(true);
+ } catch (SQLException e1) {
+ throw new IllegalArgumentException(e1);
} catch (XMLStreamException e1) {
throw new IllegalArgumentException(e1);
} catch (IOException e1) {
diff --git a/OsmAnd/src/com/osmand/OsmSQLLiteRepository.java b/OsmAnd/src/com/osmand/OsmSQLLiteRepository.java
new file mode 100644
index 0000000000..9f1a5c9efa
--- /dev/null
+++ b/OsmAnd/src/com/osmand/OsmSQLLiteRepository.java
@@ -0,0 +1,122 @@
+package com.osmand;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.osmand.data.Amenity;
+import com.osmand.data.Amenity.AmenityType;
+
+public class OsmSQLLiteRepository {
+ private static final Log log = LogUtil.getLog(OsmSQLLiteRepository.class);
+
+ private SQLiteDatabase db;
+
+ private List cachedAmenities = null;
+ private double cTopLatitude;
+ private double cBottomLatitude;
+ private double cLeftLongitude;
+ private double cRightLongitude;
+
+ private boolean isLoading = false;
+
+ protected synchronized void loadAmenitiesInAnotherThread(final double topLatitude, final double leftLongitude, final double bottomLatitude, final double rightLongitude){
+ isLoading = true;
+ new Thread(new Runnable(){
+
+ @Override
+ public void run() {
+ try {
+ cachedAmenities = internalSearch(topLatitude, leftLongitude, bottomLatitude, rightLongitude);
+ cTopLatitude = topLatitude;
+ cLeftLongitude = leftLongitude;
+ cBottomLatitude = bottomLatitude ;
+ cRightLongitude = rightLongitude;
+ } finally {
+ synchronized (this) {
+ isLoading = false;
+ }
+ }
+ }
+ }, "Searching in index...").start();
+ }
+
+
+ private List internalSearch(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude){
+ long now = System.currentTimeMillis();
+ Cursor query = db.query("poi", null, "? < latitude AND latitude < ? AND ? < longitude AND longitude < ?",
+ new String[]{Double.toString(bottomLatitude),
+ Double.toString(topLatitude), Double.toString(leftLongitude), Double.toString(rightLongitude)}, null, null, null);
+ List amenities = new ArrayList();
+ int idIndex = query.getColumnIndex("id");
+ int latitudeIndex = query.getColumnIndex("latitude");
+ int longitudeIndex = query.getColumnIndex("longitude");
+ int nameIndex = query.getColumnIndex("name");
+ int typeIndex = query.getColumnIndex("type");
+ int subtypeIndex = query.getColumnIndex("subtype");
+ if(query.moveToFirst()){
+ do {
+ Amenity am = new Amenity();
+ if(idIndex != -1){
+ am.setId(query.getLong(idIndex));
+ }
+ if(latitudeIndex != -1 && longitudeIndex != -1){
+ am.setLocation(query.getDouble(latitudeIndex), query.getDouble(longitudeIndex));
+ }
+ if(nameIndex != -1){
+ am.setName(query.getString(nameIndex));
+ }
+ if(typeIndex != -1){
+ am.setType(AmenityType.fromString(query.getString(typeIndex)));
+ }
+ if(subtypeIndex != -1){
+ am.setSubType(query.getString(subtypeIndex));
+ }
+ amenities.add(am);
+ } while(query.moveToNext());
+ }
+ query.deactivate();
+
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Search for %s done in %s ms found %s.",
+ topLatitude + " " + leftLongitude, System.currentTimeMillis() - now, amenities.size()));
+ }
+ return amenities;
+ }
+ public synchronized List searchAmenities(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude) {
+ if (db == null) {
+ return Collections.emptyList();
+ }
+ if (cTopLatitude >= topLatitude && cLeftLongitude <= leftLongitude && cRightLongitude >= rightLongitude
+ && cBottomLatitude <= bottomLatitude) {
+ return cachedAmenities;
+ }
+ if(!isLoading){
+ double h = (topLatitude - bottomLatitude);
+ double w = (rightLongitude - leftLongitude);
+ topLatitude += h;
+ leftLongitude -= w;
+ bottomLatitude -= h;
+ rightLongitude += w;
+ loadAmenitiesInAnotherThread(topLatitude, leftLongitude, bottomLatitude, rightLongitude);
+ }
+ return Collections.emptyList();
+ }
+
+ public void initialize(final IProgress progress, File file) {
+ long start = System.currentTimeMillis();
+ db = SQLiteDatabase.openOrCreateDatabase(file, null);
+ if (log.isDebugEnabled()) {
+ log.debug("Initializing db " + file.getAbsolutePath() + " " + (System.currentTimeMillis() - start) + "ms");
+ }
+ }
+
+
+
+}
diff --git a/OsmAnd/src/com/osmand/ResourceManager.java b/OsmAnd/src/com/osmand/ResourceManager.java
index b9121f7f74..aaf90992b9 100644
--- a/OsmAnd/src/com/osmand/ResourceManager.java
+++ b/OsmAnd/src/com/osmand/ResourceManager.java
@@ -74,6 +74,8 @@ public class ResourceManager {
protected OsmLuceneRepository amenityIndexSearcher = new OsmLuceneRepository();
+ protected OsmSQLLiteRepository amenityRepository = new OsmSQLLiteRepository();
+
public ResourceManager() {
// TODO start/stop this thread when needed?
@@ -280,6 +282,16 @@ public class ResourceManager {
}
});
+
+ File file = new File(Environment.getExternalStorageDirectory(), POI_PATH);
+ if (file.exists() && file.canRead()) {
+ for (File f : file.listFiles()) {
+ if(f.getName().endsWith(".db")){
+ progress.startTask("Indexing poi " + f.getName(), -1);
+ amenityRepository.initialize(progress, f);
+ }
+ }
+ }
}
}
@@ -313,6 +325,10 @@ public class ResourceManager {
return poiIndex;
}
+ public OsmSQLLiteRepository getAmenityRepository() {
+ return amenityRepository;
+ }
+
public OsmLuceneRepository getAmenityIndexSearcher(){
return amenityIndexSearcher;
diff --git a/OsmAnd/src/com/osmand/views/POIMapLayer.java b/OsmAnd/src/com/osmand/views/POIMapLayer.java
index 0559d48081..8ec70ebd15 100644
--- a/OsmAnd/src/com/osmand/views/POIMapLayer.java
+++ b/OsmAnd/src/com/osmand/views/POIMapLayer.java
@@ -8,6 +8,7 @@ import android.graphics.Paint;
import android.view.MotionEvent;
import android.widget.Toast;
+import com.osmand.OsmSQLLiteRepository;
import com.osmand.ResourceManager;
import com.osmand.data.Amenity;
import com.osmand.data.DataTileManager;
@@ -115,8 +116,20 @@ public class POIMapLayer implements OsmandMapLayer {
canvas.drawCircle(x, y, getRadiusPoi(view.getZoom()), pointAltUI);
}
}
+
+ OsmSQLLiteRepository sqlLite = ResourceManager.getResourceManager().getAmenityRepository();
+ if (sqlLite != null) {
+ objects = sqlLite.searchAmenities(topLatitude, leftLongitude, bottomLatitude, rightLongitude);
+ for (Amenity o : objects) {
+ double tileX = MapUtils.getTileNumberX(view.getZoom(), o.getLocation().getLongitude());
+ int x = (int) ((tileX - xTileLeft) * getTileSize());
+ double tileY = MapUtils.getTileNumberY(view.getZoom(), o.getLocation().getLatitude());
+ int y = (int) ((tileY - yTileUp) * getTileSize());
+ canvas.drawCircle(x, y, getRadiusPoi(view.getZoom()), pointAltUI);
+ }
+ }
if (nodeManager != null) {
- objects = nodeManager.getObjects(topLatitude, leftLongitude, bottomLatitude, rightLongitude);
+ List objects = nodeManager.getObjects(topLatitude, leftLongitude, bottomLatitude, rightLongitude);
for (Amenity o : objects) {
double tileX = MapUtils.getTileNumberX(view.getZoom(), o.getLocation().getLongitude());
int x = (int) ((tileX - xTileLeft) * getTileSize());