Small improvements

This commit is contained in:
Victor Shcherb 2011-09-24 11:57:20 +02:00
parent e7d1c174fd
commit ade397475a
6 changed files with 149 additions and 54 deletions

View file

@ -21,6 +21,7 @@ import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion;
import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion; import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion;
import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex; import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex;
import net.osmand.data.Amenity; import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.data.Building; import net.osmand.data.Building;
import net.osmand.data.City; import net.osmand.data.City;
import net.osmand.data.MapObject; import net.osmand.data.MapObject;
@ -975,9 +976,10 @@ public class BinaryMapIndexReader {
} }
public static SearchRequest<Amenity> buildSearchPoiRequest(int sleft, int sright, int stop, int sbottom, int zoom){ public static SearchRequest<Amenity> buildSearchPoiRequest(int sleft, int sright, int stop, int sbottom, int limit, int zoom){
SearchRequest<Amenity> request = new SearchRequest<Amenity>(); SearchRequest<Amenity> request = new SearchRequest<Amenity>();
request.left = sleft; request.left = sleft;
request.limit = limit;
request.right = sright; request.right = sright;
request.top = stop; request.top = stop;
request.bottom = sbottom; request.bottom = sbottom;
@ -1015,6 +1017,12 @@ public class BinaryMapIndexReader {
} }
public static interface SearchPoiTypeFilter {
public boolean accept(AmenityType type, String subcategory);
}
public static class SearchRequest<T> { public static class SearchRequest<T> {
// 31 zoom tiles // 31 zoom tiles
int left = 0; int left = 0;
@ -1027,6 +1035,7 @@ public class BinaryMapIndexReader {
TIntArrayList cacheCoordinates = new TIntArrayList(); TIntArrayList cacheCoordinates = new TIntArrayList();
TIntArrayList cacheTypes = new TIntArrayList(); TIntArrayList cacheTypes = new TIntArrayList();
SearchFilter searchFilter = null; SearchFilter searchFilter = null;
SearchPoiTypeFilter poiTypeFilter = null;
// TRACE INFO // TRACE INFO
int numberOfVisitedObjects = 0; int numberOfVisitedObjects = 0;
@ -1045,6 +1054,14 @@ public class BinaryMapIndexReader {
this.searchFilter = searchFilter; this.searchFilter = searchFilter;
} }
public void setPoiTypeFilter(SearchPoiTypeFilter poiTypeFilter) {
this.poiTypeFilter = poiTypeFilter;
}
public SearchPoiTypeFilter getPoiTypeFilter() {
return poiTypeFilter;
}
public List<T> getSearchResults() { public List<T> getSearchResults() {
return searchResults; return searchResults;
} }
@ -1207,11 +1224,18 @@ public class BinaryMapIndexReader {
// System.out.println(poiRegion.categories.get(i)); // System.out.println(poiRegion.categories.get(i));
// System.out.println(" " + poiRegion.subcategories.get(i)); // System.out.println(" " + poiRegion.subcategories.get(i));
// } // }
int sleft = MapUtils.get31TileNumberX(37.72); int sleft = MapUtils.get31TileNumberX(37.5);
int sright = MapUtils.get31TileNumberX(37.727); int sright = MapUtils.get31TileNumberX(37.9);
int stop = MapUtils.get31TileNumberY(55.814); int stop = MapUtils.get31TileNumberY(55.814);
int sbottom = MapUtils.get31TileNumberY(55.81); int sbottom = MapUtils.get31TileNumberY(55.81);
List<Amenity> results = reader.searchPoi(buildSearchPoiRequest(sleft, sright, stop, sbottom, 15)); SearchRequest<Amenity> req = buildSearchPoiRequest(sleft, sright, stop, sbottom, 15);
req.setPoiTypeFilter(new SearchPoiTypeFilter() {
@Override
public boolean accept(AmenityType type, String subcategory) {
return type == AmenityType.TRANSPORTATION && "fuel".equals(subcategory);
}
});
List<Amenity> results = reader.searchPoi(req);
for(Amenity a : results){ for(Amenity a : results){
System.out.println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation()); System.out.println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation());
} }

View file

@ -791,6 +791,21 @@ public class BinaryMapIndexWriter {
return catIndexes; return catIndexes;
} }
public void writePOICategories(TIntArrayList categories) throws IOException {
checkPeekState(POI_BOX);
OsmandOdb.OsmAndPoiCategories.Builder builder = OsmandOdb.OsmAndPoiCategories.newBuilder();
int prev = 0;
categories.sort();
for (int i = 0; i < categories.size(); i++) {
// avoid duplicates
if (i > 0 && prev != categories.get(i)) {
builder.addCategories(categories.get(i));
prev = categories.get(i);
}
}
codedOutStream.writeMessage(OsmandOdb.OsmAndPoiBox.CATEGORIES_FIELD_NUMBER, builder.build());
}
public void writePoiDataAtom(long id, int x24shift, int y24shift, String nameEn, String name, TIntArrayList types, String openingHours, public void writePoiDataAtom(long id, int x24shift, int y24shift, String nameEn, String name, TIntArrayList types, String openingHours,
String site, String phone) throws IOException { String site, String phone) throws IOException {
checkPeekState(POI_DATA); checkPeekState(POI_DATA);

View file

@ -134,13 +134,13 @@ public class BinaryMapPoiReaderAdapter {
case 0: case 0:
return; return;
case OsmandOdb.OsmAndCategoryTable.CATEGORY_FIELD_NUMBER : case OsmandOdb.OsmAndCategoryTable.CATEGORY_FIELD_NUMBER :
String cat = codedIS.readString(); String cat = codedIS.readString().intern();
region.categories.add(cat); region.categories.add(cat);
region.categoriesType.add(AmenityType.fromString(cat)); region.categoriesType.add(AmenityType.fromString(cat));
region.subcategories.add(new ArrayList<String>()); region.subcategories.add(new ArrayList<String>());
break; break;
case OsmandOdb.OsmAndCategoryTable.SUBCATEGORIES_FIELD_NUMBER : case OsmandOdb.OsmAndCategoryTable.SUBCATEGORIES_FIELD_NUMBER :
region.subcategories.get(region.subcategories.size() - 1).add(codedIS.readString()); region.subcategories.get(region.subcategories.size() - 1).add(codedIS.readString().intern());
break; break;
default: default:
skipUnknownField(t); skipUnknownField(t);
@ -165,7 +165,7 @@ public class BinaryMapPoiReaderAdapter {
case OsmandOdb.OsmAndPoiIndex.BOXES_FIELD_NUMBER : case OsmandOdb.OsmAndPoiIndex.BOXES_FIELD_NUMBER :
int length = readInt(); int length = readInt();
int oldLimit = codedIS.pushLimit(length); int oldLimit = codedIS.pushLimit(length);
readBoxField(left31, right31, top31, bottom31, 0, 0, 0, offsets, req); readBoxField(left31, right31, top31, bottom31, 0, 0, 0, offsets, req, region);
codedIS.popLimit(oldLimit); codedIS.popLimit(oldLimit);
break; break;
case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER : case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER :
@ -255,19 +255,25 @@ public class BinaryMapPoiReaderAdapter {
am.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x)); am.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
break; break;
case OsmandOdb.OsmAndPoiBoxDataAtom.CATEGORIES_FIELD_NUMBER : case OsmandOdb.OsmAndPoiBoxDataAtom.CATEGORIES_FIELD_NUMBER :
// TODO support many amenities type // TODO support many amenities type !!
int cat = codedIS.readUInt32(); int cat = codedIS.readUInt32();
int subcatId = cat >> SHIFT_BITS_CATEGORY; int subcatId = cat >> SHIFT_BITS_CATEGORY;
int catId = cat & CATEGORY_MASK; int catId = cat & CATEGORY_MASK;
if(catId < region.categoriesType.size()){ AmenityType type = AmenityType.OTHER;
am.setType(region.categoriesType.get(catId)); String subtype = "";
if (catId < region.categoriesType.size()) {
type = region.categoriesType.get(catId);
List<String> subcats = region.subcategories.get(catId); List<String> subcats = region.subcategories.get(catId);
if(subcatId < subcats.size()){ if (subcatId < subcats.size()) {
am.setSubType(subcats.get(subcatId)); subtype = subcats.get(subcatId);
} }
} else {
am.setType(AmenityType.OTHER);
} }
if (req.poiTypeFilter != null && !req.poiTypeFilter.accept(type, subtype)) {
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
return;
}
am.setSubType(subtype);
am.setType(type);
break; break;
case OsmandOdb.OsmAndPoiBoxDataAtom.ID_FIELD_NUMBER : case OsmandOdb.OsmAndPoiBoxDataAtom.ID_FIELD_NUMBER :
am.setId(codedIS.readUInt64()); am.setId(codedIS.readUInt64());
@ -293,9 +299,44 @@ public class BinaryMapPoiReaderAdapter {
} }
} }
} }
private boolean checkCategories(SearchRequest<Amenity> req, PoiRegion region) throws IOException {
while(true){
int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t);
switch (tag) {
case 0:
return false;
case OsmandOdb.OsmAndPoiCategories.CATEGORIES_FIELD_NUMBER:
AmenityType type = AmenityType.OTHER;
String subcat = "";
int cat = codedIS.readUInt32();
int subcatId = cat >> SHIFT_BITS_CATEGORY;
int catId = cat & CATEGORY_MASK;
if(catId < region.categoriesType.size()){
type = region.categoriesType.get(catId);
List<String> subcats = region.subcategories.get(catId);
if(subcatId < subcats.size()){
subcat = subcats.get(subcatId);
}
} else {
type = AmenityType.OTHER;
}
if(req.poiTypeFilter.accept(type, subcat)){
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
return true;
}
break;
default:
skipUnknownField(t);
break;
}
}
}
private void readBoxField(int left31, int right31, int top31, int bottom31, private void readBoxField(int left31, int right31, int top31, int bottom31,
int px, int py, int pzoom, TIntArrayList offsets, SearchRequest<Amenity> req) throws IOException { int px, int py, int pzoom, TIntArrayList offsets, SearchRequest<Amenity> req, PoiRegion region) throws IOException {
req.numberOfReadSubtrees++; req.numberOfReadSubtrees++;
boolean checkBox = true; boolean checkBox = true;
int zoom = pzoom; int zoom = pzoom;
@ -319,6 +360,20 @@ public class BinaryMapPoiReaderAdapter {
case OsmandOdb.OsmAndPoiBox.TOP_FIELD_NUMBER: case OsmandOdb.OsmAndPoiBox.TOP_FIELD_NUMBER:
dy = codedIS.readSInt32(); dy = codedIS.readSInt32();
break; break;
case OsmandOdb.OsmAndPoiBox.CATEGORIES_FIELD_NUMBER:
if(req.poiTypeFilter == null){
skipUnknownField(t);
} else {
int length = codedIS.readRawVarint32();
int oldLimit = codedIS.pushLimit(length);
boolean check = checkCategories(req, region);
codedIS.popLimit(oldLimit);
if(!check){
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
return;
}
}
break;
case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER: case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER:
int x = dx + (px << (zoom - pzoom)); int x = dx + (px << (zoom - pzoom));
@ -338,7 +393,7 @@ public class BinaryMapPoiReaderAdapter {
} }
int length = readInt(); int length = readInt();
int oldLimit = codedIS.pushLimit(length); int oldLimit = codedIS.pushLimit(length);
readBoxField(left31, right31, top31, bottom31, x, y, zoom, offsets, req); readBoxField(left31, right31, top31, bottom31, x, y, zoom, offsets, req, region);
codedIS.popLimit(oldLimit); codedIS.popLimit(oldLimit);
break; break;
@ -351,6 +406,5 @@ public class BinaryMapPoiReaderAdapter {
} }
} }
} }
} }

View file

@ -44,6 +44,8 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
private PreparedStatement poiPreparedStatement; private PreparedStatement poiPreparedStatement;
private static final int ZOOM_TO_SAVE_END = 16; private static final int ZOOM_TO_SAVE_END = 16;
private static final int ZOOM_TO_SAVE_START = 6; private static final int ZOOM_TO_SAVE_START = 6;
private static final int ZOOM_TO_WRITE_CATEGORIES_START = 12;
private static final int ZOOM_TO_WRITE_CATEGORIES_END = 16;
private List<Amenity> tempAmenityList = new ArrayList<Amenity>(); private List<Amenity> tempAmenityList = new ArrayList<Amenity>();
@ -154,7 +156,6 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
private void buildTypeIds(String category, String subcategory, Map<String, Map<String, Integer>> categories, private void buildTypeIds(String category, String subcategory, Map<String, Map<String, Integer>> categories,
Map<String, Integer> catIndexes, TIntArrayList types) { Map<String, Integer> catIndexes, TIntArrayList types) {
types.clear();
Map<String, Integer> map = categories.get(category); Map<String, Integer> map = categories.get(category);
if (map == null) { if (map == null) {
throw new IllegalArgumentException("Unknown category " + category); throw new IllegalArgumentException("Unknown category " + category);
@ -256,18 +257,21 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
zoomToStart = zoomToStart + level; zoomToStart = zoomToStart + level;
} }
// write tree using stack // 3.2 write tree using stack
PreparedStatement prepareStatement = poiConnection.prepareStatement("SELECT DISTINCT type, subtype FROM poi WHERE x >= ? AND x < ? AND y >= ? AND y < ?");
Map<Long, Long> fpToWriteSeeks = new LinkedHashMap<Long, Long>(); Map<Long, Long> fpToWriteSeeks = new LinkedHashMap<Long, Long>();
for (Tree<Long> subs : rootZoomsTree.getSubtrees()) { for (Tree<Long> subs : rootZoomsTree.getSubtrees()) {
writePoiBoxes(writer, subs, zoomToStart, fpToWriteSeeks); writePoiBoxes(writer, subs, zoomToStart, fpToWriteSeeks, prepareStatement,
categories, catIndexes);
} }
stat = rs.getStatement(); stat = rs.getStatement();
rs.close(); rs.close();
stat.close(); stat.close();
prepareStatement.close();
// 4. write poi data // 4. write poi data
PreparedStatement prepareStatement = poiConnection prepareStatement = poiConnection
.prepareStatement("SELECT id, x, y, name_en, name, type, subtype, opening_hours, site, phone from poi " .prepareStatement("SELECT id, x, y, name_en, name, type, subtype, opening_hours, site, phone from poi "
+ "where x >= ? AND x < ? AND y >= ? AND y < ?"); + "where x >= ? AND x < ? AND y >= ? AND y < ?");
TIntArrayList types = new TIntArrayList(); TIntArrayList types = new TIntArrayList();
@ -293,6 +297,7 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
String name = rs.getString(5); String name = rs.getString(5);
String type = rs.getString(6); String type = rs.getString(6);
String subtype = rs.getString(7); String subtype = rs.getString(7);
types.clear();
buildTypeIds(type, subtype, categories, catIndexes, types); buildTypeIds(type, subtype, categories, catIndexes, types);
String openingHours = rs.getString(8); String openingHours = rs.getString(8);
@ -313,15 +318,32 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
} }
private void writePoiBoxes(BinaryMapIndexWriter writer, Tree<Long> tree, int zoom, Map<Long, Long> fpToWriteSeeks) throws IOException { private void writePoiBoxes(BinaryMapIndexWriter writer, Tree<Long> tree, int zoom, Map<Long, Long> fpToWriteSeeks,
PreparedStatement categoriesGet, Map<String, Map<String, Integer>> categories, Map<String, Integer> catIndexes) throws IOException, SQLException {
long l = tree.getNode(); long l = tree.getNode();
int x = (int) (l >> 31); int x = (int) (l >> 31);
int y = (int) (l & ((1 << 31) - 1)); int y = (int) (l & ((1 << 31) - 1));
boolean end = zoom == ZOOM_TO_SAVE_END; boolean end = zoom == ZOOM_TO_SAVE_END;
long fp = writer.startWritePoiBox(zoom, x, y, end); long fp = writer.startWritePoiBox(zoom, x, y, end);
if(zoom >= ZOOM_TO_WRITE_CATEGORIES_START && zoom <= ZOOM_TO_WRITE_CATEGORIES_END){
categoriesGet.setInt(1, x << (31 - zoom));
categoriesGet.setInt(2, (x + 1) << (31 - zoom));
categoriesGet.setInt(3, y << (31 - zoom));
categoriesGet.setInt(4, (y + 1) << (31 - zoom));
ResultSet rs = categoriesGet.executeQuery();
TIntArrayList types = new TIntArrayList();
while(rs.next()){
String cat = rs.getString(1);
String subcat = rs.getString(2);
buildTypeIds(cat, subcat, categories, catIndexes, types);
}
writer.writePOICategories(types);
rs.close();
}
if (!end) { if (!end) {
for (Tree<Long> subTree : tree.getSubtrees()) { for (Tree<Long> subTree : tree.getSubtrees()) {
writePoiBoxes(writer, subTree, zoom + 1, fpToWriteSeeks); writePoiBoxes(writer, subTree, zoom + 1, fpToWriteSeeks, categoriesGet, categories, catIndexes);
} }
} else { } else {
fpToWriteSeeks.put(l, fp); fpToWriteSeeks.put(l, fp);
@ -403,6 +425,9 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
} }
public static void main(String[] args) throws SQLException, FileNotFoundException, IOException { public static void main(String[] args) throws SQLException, FileNotFoundException, IOException {
// TODO support multiple reading amenity types!
// TODO support string trigramms
// TODO support live results
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
IndexPoiCreator poiCreator = new IndexPoiCreator(); IndexPoiCreator poiCreator = new IndexPoiCreator();
poiCreator.poiConnection = (Connection) DBDialect.SQLITE.getDatabaseConnection( poiCreator.poiConnection = (Connection) DBDialect.SQLITE.getDatabaseConnection(

View file

@ -1,6 +1,5 @@
package net.osmand.plus; package net.osmand.plus;
import gnu.trove.list.array.TIntArrayList;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -9,14 +8,11 @@ import java.util.List;
import net.osmand.Algoritms; import net.osmand.Algoritms;
import net.osmand.LogUtil; import net.osmand.LogUtil;
import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.binary.BinaryMapIndexReader.MapIndex; import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter;
import net.osmand.binary.BinaryMapIndexReader.SearchFilter;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest; import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
import net.osmand.data.Amenity; import net.osmand.data.Amenity;
import net.osmand.data.AmenityType; import net.osmand.data.AmenityType;
import net.osmand.osm.LatLon; import net.osmand.osm.LatLon;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils; import net.osmand.osm.MapUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -59,25 +55,11 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository {
int sbottom = MapUtils.get31TileNumberY(bottomLatitude); int sbottom = MapUtils.get31TileNumberY(bottomLatitude);
int stop = MapUtils.get31TileNumberY(topLatitude); int stop = MapUtils.get31TileNumberY(topLatitude);
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(sleft, sright, stop, sbottom, 16); SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(sleft, sright, stop, sbottom, limit, 16);
// TODO types and filter and live results req.setPoiTypeFilter(new SearchPoiTypeFilter(){
req.setSearchFilter(new SearchFilter(){
@Override @Override
public boolean accept(TIntArrayList types, MapIndex root) { public boolean accept(AmenityType type, String subcategory) {
for (int j = 0; j < types.size(); j++) { return filter.acceptTypeSubtype(type, subcategory);
int wholeType = types.get(j);
TagValuePair pair = root.decodeType(wholeType);
if (pair != null) {
AmenityType type = MapRenderingTypes.getAmenityType(pair.tag, pair.value);
if (type != null) {
if(filter.acceptTypeSubtype(type, MapRenderingTypes.getAmenitySubtype(pair.tag, pair.value))){
return true;
}
}
}
}
return false;
} }
}); });
try { try {

View file

@ -28,8 +28,7 @@ public class PoiFilter {
private final boolean isStandardFilter; private final boolean isStandardFilter;
private final static int finalZoom = 6; private final static int finalZoom = 6;
private final static int initialZoom = 13; private final static int initialZoom = 14;
private final static int maxInitialCount = 200;
private int zoom = initialZoom; private int zoom = initialZoom;
private final OsmandApplication application; private final OsmandApplication application;
@ -105,7 +104,7 @@ public class PoiFilter {
public List<Amenity> initializeNewSearch(double lat, double lon, int firstTimeLimit){ public List<Amenity> initializeNewSearch(double lat, double lon, int firstTimeLimit){
zoom = getInitialZoom(); zoom = getInitialZoom();
List<Amenity> amenityList = application.getResourceManager().searchAmenities(this, lat, lon, zoom, maxInitialCount); List<Amenity> amenityList = application.getResourceManager().searchAmenities(this, lat, lon, zoom, -1);
MapUtils.sortListOfMapObject(amenityList, lat, lon); MapUtils.sortListOfMapObject(amenityList, lat, lon);
while (amenityList.size() > firstTimeLimit) { while (amenityList.size() > firstTimeLimit) {
amenityList.remove(amenityList.size() - 1); amenityList.remove(amenityList.size() - 1);
@ -115,11 +114,7 @@ public class PoiFilter {
} }
public List<Amenity> searchAgain(double lat, double lon){ public List<Amenity> searchAgain(double lat, double lon){
int limit = -1; List<Amenity> amenityList = application.getResourceManager().searchAmenities(this, lat, lon, zoom, -1);
if(zoom == getInitialZoom()){
limit = maxInitialCount;
}
List<Amenity> amenityList = application.getResourceManager().searchAmenities(this, lat, lon, zoom, limit);
MapUtils.sortListOfMapObject(amenityList, lat, lon); MapUtils.sortListOfMapObject(amenityList, lat, lon);
return amenityList; return amenityList;
} }