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.BinaryMapTransportReaderAdapter.TransportIndex;
import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.data.Building;
import net.osmand.data.City;
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>();
request.left = sleft;
request.limit = limit;
request.right = sright;
request.top = stop;
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> {
// 31 zoom tiles
int left = 0;
@ -1027,6 +1035,7 @@ public class BinaryMapIndexReader {
TIntArrayList cacheCoordinates = new TIntArrayList();
TIntArrayList cacheTypes = new TIntArrayList();
SearchFilter searchFilter = null;
SearchPoiTypeFilter poiTypeFilter = null;
// TRACE INFO
int numberOfVisitedObjects = 0;
@ -1045,6 +1054,14 @@ public class BinaryMapIndexReader {
this.searchFilter = searchFilter;
}
public void setPoiTypeFilter(SearchPoiTypeFilter poiTypeFilter) {
this.poiTypeFilter = poiTypeFilter;
}
public SearchPoiTypeFilter getPoiTypeFilter() {
return poiTypeFilter;
}
public List<T> getSearchResults() {
return searchResults;
}
@ -1207,11 +1224,18 @@ public class BinaryMapIndexReader {
// System.out.println(poiRegion.categories.get(i));
// System.out.println(" " + poiRegion.subcategories.get(i));
// }
int sleft = MapUtils.get31TileNumberX(37.72);
int sright = MapUtils.get31TileNumberX(37.727);
int sleft = MapUtils.get31TileNumberX(37.5);
int sright = MapUtils.get31TileNumberX(37.9);
int stop = MapUtils.get31TileNumberY(55.814);
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){
System.out.println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation());
}

View file

@ -791,6 +791,21 @@ public class BinaryMapIndexWriter {
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,
String site, String phone) throws IOException {
checkPeekState(POI_DATA);

View file

@ -134,13 +134,13 @@ public class BinaryMapPoiReaderAdapter {
case 0:
return;
case OsmandOdb.OsmAndCategoryTable.CATEGORY_FIELD_NUMBER :
String cat = codedIS.readString();
String cat = codedIS.readString().intern();
region.categories.add(cat);
region.categoriesType.add(AmenityType.fromString(cat));
region.subcategories.add(new ArrayList<String>());
break;
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;
default:
skipUnknownField(t);
@ -165,7 +165,7 @@ public class BinaryMapPoiReaderAdapter {
case OsmandOdb.OsmAndPoiIndex.BOXES_FIELD_NUMBER :
int length = readInt();
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);
break;
case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER :
@ -255,19 +255,25 @@ public class BinaryMapPoiReaderAdapter {
am.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
break;
case OsmandOdb.OsmAndPoiBoxDataAtom.CATEGORIES_FIELD_NUMBER :
// TODO support many amenities type
// TODO support many amenities type !!
int cat = codedIS.readUInt32();
int subcatId = cat >> SHIFT_BITS_CATEGORY;
int catId = cat & CATEGORY_MASK;
if(catId < region.categoriesType.size()){
am.setType(region.categoriesType.get(catId));
AmenityType type = AmenityType.OTHER;
String subtype = "";
if (catId < region.categoriesType.size()) {
type = region.categoriesType.get(catId);
List<String> subcats = region.subcategories.get(catId);
if(subcatId < subcats.size()){
am.setSubType(subcats.get(subcatId));
if (subcatId < subcats.size()) {
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;
case OsmandOdb.OsmAndPoiBoxDataAtom.ID_FIELD_NUMBER :
am.setId(codedIS.readUInt64());
@ -294,8 +300,43 @@ 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,
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++;
boolean checkBox = true;
int zoom = pzoom;
@ -319,6 +360,20 @@ public class BinaryMapPoiReaderAdapter {
case OsmandOdb.OsmAndPoiBox.TOP_FIELD_NUMBER:
dy = codedIS.readSInt32();
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:
int x = dx + (px << (zoom - pzoom));
@ -338,7 +393,7 @@ public class BinaryMapPoiReaderAdapter {
}
int length = readInt();
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);
break;
@ -352,5 +407,4 @@ public class BinaryMapPoiReaderAdapter {
}
}
}

View file

@ -44,6 +44,8 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
private PreparedStatement poiPreparedStatement;
private static final int ZOOM_TO_SAVE_END = 16;
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>();
@ -154,7 +156,6 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
private void buildTypeIds(String category, String subcategory, Map<String, Map<String, Integer>> categories,
Map<String, Integer> catIndexes, TIntArrayList types) {
types.clear();
Map<String, Integer> map = categories.get(category);
if (map == null) {
throw new IllegalArgumentException("Unknown category " + category);
@ -256,18 +257,21 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
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>();
for (Tree<Long> subs : rootZoomsTree.getSubtrees()) {
writePoiBoxes(writer, subs, zoomToStart, fpToWriteSeeks);
writePoiBoxes(writer, subs, zoomToStart, fpToWriteSeeks, prepareStatement,
categories, catIndexes);
}
stat = rs.getStatement();
rs.close();
stat.close();
prepareStatement.close();
// 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 "
+ "where x >= ? AND x < ? AND y >= ? AND y < ?");
TIntArrayList types = new TIntArrayList();
@ -293,6 +297,7 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
String name = rs.getString(5);
String type = rs.getString(6);
String subtype = rs.getString(7);
types.clear();
buildTypeIds(type, subtype, categories, catIndexes, types);
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();
int x = (int) (l >> 31);
int y = (int) (l & ((1 << 31) - 1));
boolean end = zoom == ZOOM_TO_SAVE_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) {
for (Tree<Long> subTree : tree.getSubtrees()) {
writePoiBoxes(writer, subTree, zoom + 1, fpToWriteSeeks);
writePoiBoxes(writer, subTree, zoom + 1, fpToWriteSeeks, categoriesGet, categories, catIndexes);
}
} else {
fpToWriteSeeks.put(l, fp);
@ -403,6 +425,9 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
}
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();
IndexPoiCreator poiCreator = new IndexPoiCreator();
poiCreator.poiConnection = (Connection) DBDialect.SQLITE.getDatabaseConnection(

View file

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

View file

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