add new address index format support

git-svn-id: https://osmand.googlecode.com/svn/trunk@625 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-11-02 21:59:47 +00:00
parent 425d0d1fcc
commit ac495120d9
15 changed files with 1296 additions and 609 deletions

View file

@ -10,6 +10,7 @@ public class ToDoConstants {
// TODO max 101
// !!! Fix progress in DataExtractionOsm
// !!! Fix files in IndexCreator (create one file!)
// Outside base 0.4 release
// 69. Add phone and site information to POI (enable call to POI and open site)

View file

@ -13,6 +13,7 @@ import net.osmand.Algoritms;
import net.osmand.LogUtil;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.data.PostCode;
import net.osmand.data.Street;
import net.osmand.data.City.CityType;
import net.osmand.osm.MapUtils;
@ -42,11 +43,15 @@ public class BinaryMapIndexReader {
}
private void init() throws IOException {
boolean initCorrectly = false;
while(true){
int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t);
switch (tag) {
case 0:
if(!initCorrectly){
throw new IOException("Corrupted file. It should be ended as it starts with version"); //$NON-NLS-1$
}
return;
case OsmandOdb.OsmAndStructure.VERSION_FIELD_NUMBER :
version = codedIS.readUInt32();
@ -60,12 +65,17 @@ public class BinaryMapIndexReader {
codedIS.seek(filePointer + length);
break;
case OsmandOdb.OsmAndStructure.ADDRESSINDEX_FIELD_NUMBER:
length = readInt();
filePointer = codedIS.getTotalBytesRead();
oldLimit = codedIS.pushLimit(length);
readAddressIndex();
AddressRegion region = new AddressRegion();
region.length = readInt();
region.fileOffset = codedIS.getTotalBytesRead();
oldLimit = codedIS.pushLimit(region.length);
readAddressIndex(region);
codedIS.popLimit(oldLimit);
codedIS.seek(filePointer + length);
codedIS.seek(region.fileOffset + region.length);
break;
case OsmandOdb.OsmAndStructure.VERSIONCONFIRM_FIELD_NUMBER :
int cversion = codedIS.readUInt32();
initCorrectly = cversion == version;
break;
default:
skipUnknownField(t);
@ -84,8 +94,7 @@ public class BinaryMapIndexReader {
}
}
private void readAddressIndex() throws IOException {
AddressRegion region = new AddressRegion();
private void readAddressIndex(AddressRegion region) throws IOException {
while(true){
int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t);
@ -268,6 +277,34 @@ public class BinaryMapIndexReader {
throw new IllegalArgumentException(name);
}
public List<PostCode> getPostcodes(String region) throws IOException {
List<PostCode> postcodes = new ArrayList<PostCode>();
AddressRegion r = getRegionByName(region);
if(r.postcodesOffset != -1){
codedIS.seek(r.postcodesOffset);
int len = readInt();
int old = codedIS.pushLimit(len);
readPostcodes(postcodes);
codedIS.popLimit(old);
}
return postcodes;
}
public PostCode getPostcodeByName(String region, String name) throws IOException {
AddressRegion r = getRegionByName(region);
if (r.postcodesOffset != -1) {
codedIS.seek(r.postcodesOffset);
int len = readInt();
int old = codedIS.pushLimit(len);
PostCode p = findPostcode(name);
if (p != null) {
return p;
}
codedIS.popLimit(old);
}
return null;
}
public List<City> getCities(String region) throws IOException {
List<City> cities = new ArrayList<City>();
AddressRegion r = getRegionByName(region);
@ -294,6 +331,51 @@ public class BinaryMapIndexReader {
return cities;
}
private void readPostcodes(List<PostCode> postcodes) throws IOException{
while(true){
int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t);
switch (tag) {
case 0:
return;
case OsmandOdb.PostcodesIndex.POSTCODES_FIELD_NUMBER :
int offset = codedIS.getTotalBytesRead();
int length = codedIS.readRawVarint32();
int oldLimit = codedIS.pushLimit(length);
postcodes.add(readPostcode(null, offset, false, null));
codedIS.popLimit(oldLimit);
break;
default:
skipUnknownField(t);
break;
}
}
}
private PostCode findPostcode(String name) throws IOException{
while(true){
int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t);
switch (tag) {
case 0:
return null;
case OsmandOdb.PostcodesIndex.POSTCODES_FIELD_NUMBER :
int offset = codedIS.getTotalBytesRead();
int length = codedIS.readRawVarint32();
int oldLimit = codedIS.pushLimit(length);
PostCode p = readPostcode(null, offset, true, name);
codedIS.popLimit(oldLimit);
if(p != null){
return p;
}
break;
default:
skipUnknownField(t);
break;
}
}
}
private void readCities(List<City> cities) throws IOException{
while(true){
int t = codedIS.readTag();
@ -317,7 +399,7 @@ public class BinaryMapIndexReader {
}
public void preloadStreets(City c) throws IOException {
// TODO check city belongs to that address repository
checkAddressIndex(c.getFileOffset());
codedIS.seek(c.getFileOffset());
int size = codedIS.readRawVarint32();
int old = codedIS.pushLimit(size);
@ -325,15 +407,87 @@ public class BinaryMapIndexReader {
codedIS.popLimit(old);
}
public void preloadBuildings(Street s) throws IOException {
// TODO check street belongs to that address repository
codedIS.seek(s.getFileOffset());
public void preloadStreets(PostCode p) throws IOException {
checkAddressIndex(p.getFileOffset());
codedIS.seek(p.getFileOffset());
int size = codedIS.readRawVarint32();
int old = codedIS.pushLimit(size);
readStreet(s, true, 0, 0);
readPostcode(p, p.getFileOffset(), true, null);
codedIS.popLimit(old);
}
private void checkAddressIndex(int offset){
boolean ok = false;
for(AddressRegion r : addressIndexes){
if(offset >= r.fileOffset && offset <= (r.length + r.fileOffset)){
ok = true;
break;
}
}
if(!ok){
throw new IllegalArgumentException("Illegal offset " + offset); //$NON-NLS-1$
}
}
public void preloadBuildings(Street s) throws IOException {
checkAddressIndex(s.getFileOffset());
codedIS.seek(s.getFileOffset());
int size = codedIS.readRawVarint32();
int old = codedIS.pushLimit(size);
readStreet(s, true, 0, 0, null);
codedIS.popLimit(old);
}
private PostCode readPostcode(PostCode p, int fileOffset, boolean loadStreets, String postcodeFilter) throws IOException{
int x = 0;
int y = 0;
while(true){
int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t);
switch (tag) {
case 0:
p.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
p.setFileOffset(fileOffset);
return p;
case OsmandOdb.PostcodeIndex.POSTCODE_FIELD_NUMBER :
String name = codedIS.readString();
if(postcodeFilter != null && postcodeFilter.equalsIgnoreCase(name)){
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
return null;
}
if(p == null){
p = new PostCode(name);
}
p.setName(name);
break;
case OsmandOdb.PostcodeIndex.X_FIELD_NUMBER :
x = codedIS.readFixed32();
break;
case OsmandOdb.PostcodeIndex.Y_FIELD_NUMBER :
y = codedIS.readFixed32();
break;
case OsmandOdb.PostcodeIndex.STREETS_FIELD_NUMBER :
int offset = codedIS.getTotalBytesRead();
int length = codedIS.readRawVarint32();
if(loadStreets){
Street s = new Street(null);
int oldLimit = codedIS.pushLimit(length);
s.setFileOffset(offset);
readStreet(s, true, x >> 7, y >> 7, p.getName());
p.registerStreet(s, false);
codedIS.popLimit(oldLimit);
} else {
codedIS.skipRawBytes(length);
}
break;
default:
skipUnknownField(t);
break;
}
}
}
private City readCity(City c, int fileOffset, boolean loadStreets) throws IOException{
@ -375,7 +529,7 @@ public class BinaryMapIndexReader {
Street s = new Street(c);
int oldLimit = codedIS.pushLimit(length);
s.setFileOffset(offset);
readStreet(s, false, x >> 7, y >> 7);
readStreet(s, false, x >> 7, y >> 7, null);
c.registerStreet(s);
codedIS.popLimit(oldLimit);
} else {
@ -389,7 +543,7 @@ public class BinaryMapIndexReader {
}
}
private Street readStreet(Street s, boolean loadBuildings, int city24X, int city24Y) throws IOException{
private Street readStreet(Street s, boolean loadBuildings, int city24X, int city24Y, String postcodeFilter) throws IOException{
int x = 0;
int y = 0;
boolean loadLocation = city24X != 0 || city24Y != 0;
@ -433,7 +587,9 @@ public class BinaryMapIndexReader {
if(loadBuildings){
int oldLimit = codedIS.pushLimit(length);
Building b = readBuilding(offset, x, y);
s.registerBuilding(b);
if (postcodeFilter == null || postcodeFilter.equalsIgnoreCase(b.getPostcode())) {
s.registerBuilding(b);
}
codedIS.popLimit(oldLimit);
} else {
codedIS.skipRawBytes(length);
@ -843,16 +999,21 @@ public class BinaryMapIndexReader {
String name;
String enName;
int fileOffset = 0;
int length = 0;
int postcodesOffset = -1;
int villagesOffset = -1;
int citiesOffset = -1;
}
public static void main(String[] args) throws IOException {
// RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Minsk.map.pbf"), "r");
RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Belarus.map.pbf"), "r");
RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Minsk.map.pbf"), "r");
// RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Belarus.map.pbf"), "r");
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
System.out.println("VERSION " + reader.getVersion());
// test search
// int sleft = MapUtils.get31TileNumberX(27.596);
// int sright = MapUtils.get31TileNumberX(27.599);
// int stop = MapUtils.get31TileNumberY(53.921);
@ -864,6 +1025,8 @@ public class BinaryMapIndexReader {
// System.out.println(" " + obj.getName());
// }
// }
// test address index search
String reg = reader.getRegionNames().get(0);
long time = System.currentTimeMillis();
List<City> cs = reader.getCities(reg);
@ -877,8 +1040,13 @@ public class BinaryMapIndexReader {
System.out.println(c.getName() + " " + c.getLocation() + " " + c.getStreets().size() + " " + buildings);
}
List<City> villages = reader.getVillages(reg);
System.out.println(villages.size());
System.out.println(System.currentTimeMillis() - time);
List<PostCode> postcodes = reader.getPostcodes(reg);
for(PostCode c : postcodes){
reader.preloadStreets(c);
// System.out.println(c.getName());
}
System.out.println("Villages " + villages.size());
System.out.println("Time " + (System.currentTimeMillis() - time));
}
}

View file

@ -88,6 +88,11 @@ public class BinaryMapIndexWriter {
codedOutStream.writeInt32(OsmandOdb.OsmAndStructure.VERSION_FIELD_NUMBER, IndexConstants.BINARY_MAP_VERSION);
state.push(OSMAND_STRUCTURE_INIT);
}
public void finishWriting(){
}
private void preserveInt32Size() throws IOException {
codedOutStream.flush();
@ -411,15 +416,18 @@ public class BinaryMapIndexWriter {
public void writePostcode(String postcode, Collection<Street> streets) throws IOException {
checkPeekState(POSTCODES_INDEX_INIT);
LatLon loc = null;
if(streets.isEmpty()){
return;
}
postcode = postcode.toUpperCase();
LatLon loc = streets.iterator().next().getLocation();
PostcodeIndex.Builder post = OsmandOdb.PostcodeIndex.newBuilder();
post.setPostcode(postcode);
post.setX(MapUtils.get31TileNumberX(loc.getLongitude()));
post.setY(MapUtils.get31TileNumberY(loc.getLatitude()));
for(Street s : streets){
if(loc == null){
loc = s.getLocation();
}
StreetIndex streetInd = createStreetAndBuildings(s, loc, postcode);
post.addStreets(streetInd);
}
@ -477,8 +485,8 @@ public class BinaryMapIndexWriter {
}
private void checkPeekState(int... states) {
for(int i=0;i<states.length; i++){
if(states[i] == state.peek()){
for (int i = 0; i < states.length; i++) {
if (states[i] == state.peek()) {
return;
}
}
@ -493,7 +501,8 @@ public class BinaryMapIndexWriter {
}
public void close() throws IOException{
assert state.peek() == OSMAND_STRUCTURE_INIT;
checkPeekState(OSMAND_STRUCTURE_INIT);
codedOutStream.writeInt32(OsmandOdb.OsmAndStructure.VERSIONCONFIRM_FIELD_NUMBER, IndexConstants.BINARY_MAP_VERSION);
codedOutStream.flush();
}
}

View file

@ -66,10 +66,18 @@ public final class OsmandOdb {
return addressIndex_.get(index);
}
// required uint32 versionConfirm = 32;
public static final int VERSIONCONFIRM_FIELD_NUMBER = 32;
private boolean hasVersionConfirm;
private int versionConfirm_ = 0;
public boolean hasVersionConfirm() { return hasVersionConfirm; }
public int getVersionConfirm() { return versionConfirm_; }
private void initFields() {
}
public final boolean isInitialized() {
if (!hasVersion) return false;
if (!hasVersionConfirm) return false;
for (net.osmand.binary.OsmandOdb.OsmAndMapIndex element : getMapIndexList()) {
if (!element.isInitialized()) return false;
}
@ -91,6 +99,9 @@ public final class OsmandOdb {
for (net.osmand.binary.OsmandOdb.OsmAndAddressIndex element : getAddressIndexList()) {
output.writeMessage(3, element);
}
if (hasVersionConfirm()) {
output.writeUInt32(32, getVersionConfirm());
}
getUnknownFields().writeTo(output);
}
@ -112,6 +123,10 @@ public final class OsmandOdb {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(3, element);
}
if (hasVersionConfirm()) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(32, getVersionConfirm());
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@ -293,6 +308,9 @@ public final class OsmandOdb {
}
result.addressIndex_.addAll(other.addressIndex_);
}
if (other.hasVersionConfirm()) {
setVersionConfirm(other.getVersionConfirm());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@ -334,6 +352,10 @@ public final class OsmandOdb {
addAddressIndex(subBuilder.buildPartial());
break;
}
case 256: {
setVersionConfirm(input.readUInt32());
break;
}
}
}
}
@ -459,6 +481,24 @@ public final class OsmandOdb {
return this;
}
// required uint32 versionConfirm = 32;
public boolean hasVersionConfirm() {
return result.hasVersionConfirm();
}
public int getVersionConfirm() {
return result.getVersionConfirm();
}
public Builder setVersionConfirm(int value) {
result.hasVersionConfirm = true;
result.versionConfirm_ = value;
return this;
}
public Builder clearVersionConfirm() {
result.hasVersionConfirm = false;
result.versionConfirm_ = 0;
return this;
}
// @@protoc_insertion_point(builder_scope:OsmAndStructure)
}
@ -4147,8 +4187,8 @@ public final class OsmandOdb {
public boolean hasY() { return hasY; }
public int getY() { return y_; }
// repeated .StreetIndex streets = 7;
public static final int STREETS_FIELD_NUMBER = 7;
// repeated .StreetIndex streets = 10;
public static final int STREETS_FIELD_NUMBER = 10;
private java.util.List<net.osmand.binary.OsmandOdb.StreetIndex> streets_ =
java.util.Collections.emptyList();
public java.util.List<net.osmand.binary.OsmandOdb.StreetIndex> getStreetsList() {
@ -4194,7 +4234,7 @@ public final class OsmandOdb {
output.writeFixed32(6, getY());
}
for (net.osmand.binary.OsmandOdb.StreetIndex element : getStreetsList()) {
output.writeMessage(7, element);
output.writeMessage(10, element);
}
getUnknownFields().writeTo(output);
}
@ -4231,7 +4271,7 @@ public final class OsmandOdb {
}
for (net.osmand.binary.OsmandOdb.StreetIndex element : getStreetsList()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(7, element);
.computeMessageSize(10, element);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
@ -4468,7 +4508,7 @@ public final class OsmandOdb {
setY(input.readFixed32());
break;
}
case 58: {
case 82: {
net.osmand.binary.OsmandOdb.StreetIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.StreetIndex.newBuilder();
input.readMessage(subBuilder, extensionRegistry);
addStreets(subBuilder.buildPartial());
@ -4593,7 +4633,7 @@ public final class OsmandOdb {
return this;
}
// repeated .StreetIndex streets = 7;
// repeated .StreetIndex streets = 10;
public java.util.List<net.osmand.binary.OsmandOdb.StreetIndex> getStreetsList() {
return java.util.Collections.unmodifiableList(result.streets_);
}
@ -4690,6 +4730,20 @@ public final class OsmandOdb {
public boolean hasPostcode() { return hasPostcode; }
public java.lang.String getPostcode() { return postcode_; }
// required fixed32 x = 2;
public static final int X_FIELD_NUMBER = 2;
private boolean hasX;
private int x_ = 0;
public boolean hasX() { return hasX; }
public int getX() { return x_; }
// required fixed32 y = 3;
public static final int Y_FIELD_NUMBER = 3;
private boolean hasY;
private int y_ = 0;
public boolean hasY() { return hasY; }
public int getY() { return y_; }
// repeated .StreetIndex streets = 5;
public static final int STREETS_FIELD_NUMBER = 5;
private java.util.List<net.osmand.binary.OsmandOdb.StreetIndex> streets_ =
@ -4706,6 +4760,8 @@ public final class OsmandOdb {
}
public final boolean isInitialized() {
if (!hasPostcode) return false;
if (!hasX) return false;
if (!hasY) return false;
for (net.osmand.binary.OsmandOdb.StreetIndex element : getStreetsList()) {
if (!element.isInitialized()) return false;
}
@ -4718,6 +4774,12 @@ public final class OsmandOdb {
if (hasPostcode()) {
output.writeString(1, getPostcode());
}
if (hasX()) {
output.writeFixed32(2, getX());
}
if (hasY()) {
output.writeFixed32(3, getY());
}
for (net.osmand.binary.OsmandOdb.StreetIndex element : getStreetsList()) {
output.writeMessage(5, element);
}
@ -4734,6 +4796,14 @@ public final class OsmandOdb {
size += com.google.protobuf.CodedOutputStream
.computeStringSize(1, getPostcode());
}
if (hasX()) {
size += com.google.protobuf.CodedOutputStream
.computeFixed32Size(2, getX());
}
if (hasY()) {
size += com.google.protobuf.CodedOutputStream
.computeFixed32Size(3, getY());
}
for (net.osmand.binary.OsmandOdb.StreetIndex element : getStreetsList()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(5, element);
@ -4903,6 +4973,12 @@ public final class OsmandOdb {
if (other.hasPostcode()) {
setPostcode(other.getPostcode());
}
if (other.hasX()) {
setX(other.getX());
}
if (other.hasY()) {
setY(other.getY());
}
if (!other.streets_.isEmpty()) {
if (result.streets_.isEmpty()) {
result.streets_ = new java.util.ArrayList<net.osmand.binary.OsmandOdb.StreetIndex>();
@ -4938,6 +5014,14 @@ public final class OsmandOdb {
setPostcode(input.readString());
break;
}
case 21: {
setX(input.readFixed32());
break;
}
case 29: {
setY(input.readFixed32());
break;
}
case 42: {
net.osmand.binary.OsmandOdb.StreetIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.StreetIndex.newBuilder();
input.readMessage(subBuilder, extensionRegistry);
@ -4970,6 +5054,42 @@ public final class OsmandOdb {
return this;
}
// required fixed32 x = 2;
public boolean hasX() {
return result.hasX();
}
public int getX() {
return result.getX();
}
public Builder setX(int value) {
result.hasX = true;
result.x_ = value;
return this;
}
public Builder clearX() {
result.hasX = false;
result.x_ = 0;
return this;
}
// required fixed32 y = 3;
public boolean hasY() {
return result.hasY();
}
public int getY() {
return result.getY();
}
public Builder setY(int value) {
result.hasY = true;
result.y_ = value;
return this;
}
public Builder clearY() {
result.hasY = false;
result.y_ = 0;
return this;
}
// repeated .StreetIndex streets = 5;
public java.util.List<net.osmand.binary.OsmandOdb.StreetIndex> getStreetsList() {
return java.util.Collections.unmodifiableList(result.streets_);
@ -5095,8 +5215,8 @@ public final class OsmandOdb {
public boolean hasY() { return hasY; }
public int getY() { return y_; }
// repeated .BuildingIndex buildings = 5;
public static final int BUILDINGS_FIELD_NUMBER = 5;
// repeated .BuildingIndex buildings = 10;
public static final int BUILDINGS_FIELD_NUMBER = 10;
private java.util.List<net.osmand.binary.OsmandOdb.BuildingIndex> buildings_ =
java.util.Collections.emptyList();
public java.util.List<net.osmand.binary.OsmandOdb.BuildingIndex> getBuildingsList() {
@ -5134,12 +5254,12 @@ public final class OsmandOdb {
if (hasY()) {
output.writeSInt32(4, getY());
}
for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) {
output.writeMessage(5, element);
}
if (hasId()) {
output.writeUInt64(6, getId());
}
for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) {
output.writeMessage(10, element);
}
getUnknownFields().writeTo(output);
}
@ -5165,14 +5285,14 @@ public final class OsmandOdb {
size += com.google.protobuf.CodedOutputStream
.computeSInt32Size(4, getY());
}
for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(5, element);
}
if (hasId()) {
size += com.google.protobuf.CodedOutputStream
.computeUInt64Size(6, getId());
}
for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(10, element);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@ -5397,16 +5517,16 @@ public final class OsmandOdb {
setY(input.readSInt32());
break;
}
case 42: {
case 48: {
setId(input.readUInt64());
break;
}
case 82: {
net.osmand.binary.OsmandOdb.BuildingIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.BuildingIndex.newBuilder();
input.readMessage(subBuilder, extensionRegistry);
addBuildings(subBuilder.buildPartial());
break;
}
case 48: {
setId(input.readUInt64());
break;
}
}
}
}
@ -5508,7 +5628,7 @@ public final class OsmandOdb {
return this;
}
// repeated .BuildingIndex buildings = 5;
// repeated .BuildingIndex buildings = 10;
public java.util.List<net.osmand.binary.OsmandOdb.BuildingIndex> getBuildingsList() {
return java.util.Collections.unmodifiableList(result.buildings_);
}
@ -6136,39 +6256,41 @@ public final class OsmandOdb {
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\024src/osmand_odb.proto\"p\n\017OsmAndStructur" +
"e\022\017\n\007version\030\001 \002(\r\022!\n\010mapIndex\030\002 \003(\0132\017.O" +
"smAndMapIndex\022)\n\014addressIndex\030\003 \003(\0132\023.Os" +
"mAndAddressIndex\"/\n\016OsmAndMapIndex\022\035\n\006le" +
"vels\030\001 \003(\0132\r.MapRootLevel\"\202\001\n\014MapRootLev" +
"el\022\017\n\007maxZoom\030\001 \002(\005\022\017\n\007minZoom\030\002 \002(\005\022\014\n\004" +
"left\030\003 \002(\005\022\r\n\005right\030\004 \002(\005\022\013\n\003top\030\005 \002(\005\022\016" +
"\n\006bottom\030\006 \002(\005\022\026\n\004root\030\007 \003(\0132\010.MapTree\"\253" +
"\001\n\007MapTree\022\014\n\004left\030\001 \002(\021\022\r\n\005right\030\002 \002(\021\022" +
"\013\n\003top\030\003 \002(\021\022\016\n\006bottom\030\004 \002(\021\022!\n\013stringTa",
"ble\030\005 \001(\0132\014.StringTable\022\016\n\006baseId\030\006 \001(\004\022" +
"\032\n\010subtrees\030\007 \003(\0132\010.MapTree\022\027\n\005leafs\030\010 \003" +
"(\0132\010.MapData\"\030\n\013StringTable\022\t\n\001s\030\001 \003(\t\"v" +
"\n\007MapData\022\023\n\013coordinates\030\001 \002(\014\022\r\n\005types\030" +
"\002 \002(\014\022\n\n\002id\030\003 \002(\022\022\020\n\010stringId\030\004 \001(\r\022\024\n\014r" +
"estrictions\030\005 \001(\014\022\023\n\013highwayMeta\030\006 \001(\005\"\225" +
"\001\n\022OsmAndAddressIndex\022\014\n\004name\030\001 \002(\t\022\017\n\007n" +
"ame_en\030\002 \001(\t\022\034\n\006cities\030\005 \001(\0132\014.CitiesInd" +
"ex\022\"\n\tpostcodes\030\006 \001(\0132\017.PostcodesIndex\022\036" +
"\n\010villages\030\007 \001(\0132\014.CitiesIndex\")\n\013Cities",
"Index\022\032\n\006cities\030\001 \003(\0132\n.CityIndex\"3\n\016Pos" +
"tcodesIndex\022!\n\tpostcodes\030\001 \003(\0132\016.Postcod" +
"eIndex\"~\n\tCityIndex\022\021\n\tcity_type\030\001 \002(\r\022\014" +
"\n\004name\030\002 \002(\t\022\017\n\007name_en\030\003 \001(\t\022\n\n\002id\030\004 \001(" +
"\004\022\t\n\001x\030\005 \002(\007\022\t\n\001y\030\006 \002(\007\022\035\n\007streets\030\007 \003(\013" +
"2\014.StreetIndex\"@\n\rPostcodeIndex\022\020\n\010postc" +
"ode\030\001 \002(\t\022\035\n\007streets\030\005 \003(\0132\014.StreetIndex" +
"\"q\n\013StreetIndex\022\014\n\004name\030\001 \002(\t\022\017\n\007name_en" +
"\030\002 \001(\t\022\n\n\002id\030\006 \001(\004\022\t\n\001x\030\003 \002(\021\022\t\n\001y\030\004 \002(\021" +
"\022!\n\tbuildings\030\005 \003(\0132\016.BuildingIndex\"b\n\rB",
"uildingIndex\022\014\n\004name\030\001 \002(\t\022\017\n\007name_en\030\002 " +
"\001(\t\022\n\n\002id\030\005 \001(\004\022\020\n\010postcode\030\006 \001(\t\022\t\n\001x\030\003" +
" \002(\021\022\t\n\001y\030\004 \002(\021B\023\n\021net.osmand.binary"
"\n\024src/osmand_odb.proto\"\210\001\n\017OsmAndStructu" +
"re\022\017\n\007version\030\001 \002(\r\022!\n\010mapIndex\030\002 \003(\0132\017." +
"OsmAndMapIndex\022)\n\014addressIndex\030\003 \003(\0132\023.O" +
"smAndAddressIndex\022\026\n\016versionConfirm\030 \002(" +
"\r\"/\n\016OsmAndMapIndex\022\035\n\006levels\030\001 \003(\0132\r.Ma" +
"pRootLevel\"\202\001\n\014MapRootLevel\022\017\n\007maxZoom\030\001" +
" \002(\005\022\017\n\007minZoom\030\002 \002(\005\022\014\n\004left\030\003 \002(\005\022\r\n\005r" +
"ight\030\004 \002(\005\022\013\n\003top\030\005 \002(\005\022\016\n\006bottom\030\006 \002(\005\022" +
"\026\n\004root\030\007 \003(\0132\010.MapTree\"\253\001\n\007MapTree\022\014\n\004l" +
"eft\030\001 \002(\021\022\r\n\005right\030\002 \002(\021\022\013\n\003top\030\003 \002(\021\022\016\n",
"\006bottom\030\004 \002(\021\022!\n\013stringTable\030\005 \001(\0132\014.Str" +
"ingTable\022\016\n\006baseId\030\006 \001(\004\022\032\n\010subtrees\030\007 \003" +
"(\0132\010.MapTree\022\027\n\005leafs\030\010 \003(\0132\010.MapData\"\030\n" +
"\013StringTable\022\t\n\001s\030\001 \003(\t\"v\n\007MapData\022\023\n\013co" +
"ordinates\030\001 \002(\014\022\r\n\005types\030\002 \002(\014\022\n\n\002id\030\003 \002" +
"(\022\022\020\n\010stringId\030\004 \001(\r\022\024\n\014restrictions\030\005 \001" +
"(\014\022\023\n\013highwayMeta\030\006 \001(\005\"\225\001\n\022OsmAndAddres" +
"sIndex\022\014\n\004name\030\001 \002(\t\022\017\n\007name_en\030\002 \001(\t\022\034\n" +
"\006cities\030\005 \001(\0132\014.CitiesIndex\022\"\n\tpostcodes" +
"\030\006 \001(\0132\017.PostcodesIndex\022\036\n\010villages\030\007 \001(",
"\0132\014.CitiesIndex\")\n\013CitiesIndex\022\032\n\006cities" +
"\030\001 \003(\0132\n.CityIndex\"3\n\016PostcodesIndex\022!\n\t" +
"postcodes\030\001 \003(\0132\016.PostcodeIndex\"~\n\tCityI" +
"ndex\022\021\n\tcity_type\030\001 \002(\r\022\014\n\004name\030\002 \002(\t\022\017\n" +
"\007name_en\030\003 \001(\t\022\n\n\002id\030\004 \001(\004\022\t\n\001x\030\005 \002(\007\022\t\n" +
"\001y\030\006 \002(\007\022\035\n\007streets\030\n \003(\0132\014.StreetIndex\"" +
"V\n\rPostcodeIndex\022\020\n\010postcode\030\001 \002(\t\022\t\n\001x\030" +
"\002 \002(\007\022\t\n\001y\030\003 \002(\007\022\035\n\007streets\030\005 \003(\0132\014.Stre" +
"etIndex\"q\n\013StreetIndex\022\014\n\004name\030\001 \002(\t\022\017\n\007" +
"name_en\030\002 \001(\t\022\n\n\002id\030\006 \001(\004\022\t\n\001x\030\003 \002(\021\022\t\n\001",
"y\030\004 \002(\021\022!\n\tbuildings\030\n \003(\0132\016.BuildingInd" +
"ex\"b\n\rBuildingIndex\022\014\n\004name\030\001 \002(\t\022\017\n\007nam" +
"e_en\030\002 \001(\t\022\n\n\002id\030\005 \001(\004\022\020\n\010postcode\030\006 \001(\t" +
"\022\t\n\001x\030\003 \002(\021\022\t\n\001y\030\004 \002(\021B\023\n\021net.osmand.bin" +
"ary"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@ -6180,7 +6302,7 @@ public final class OsmandOdb {
internal_static_OsmAndStructure_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_OsmAndStructure_descriptor,
new java.lang.String[] { "Version", "MapIndex", "AddressIndex", },
new java.lang.String[] { "Version", "MapIndex", "AddressIndex", "VersionConfirm", },
net.osmand.binary.OsmandOdb.OsmAndStructure.class,
net.osmand.binary.OsmandOdb.OsmAndStructure.Builder.class);
internal_static_OsmAndMapIndex_descriptor =
@ -6260,7 +6382,7 @@ public final class OsmandOdb {
internal_static_PostcodeIndex_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_PostcodeIndex_descriptor,
new java.lang.String[] { "Postcode", "Streets", },
new java.lang.String[] { "Postcode", "X", "Y", "Streets", },
net.osmand.binary.OsmandOdb.PostcodeIndex.class,
net.osmand.binary.OsmandOdb.PostcodeIndex.Builder.class);
internal_static_StreetIndex_descriptor =

View file

@ -3,17 +3,15 @@ package net.osmand.data;
import java.text.Collator;
import java.util.Comparator;
public class CityComparator implements Comparator<City>{
public class MapObjectComparator implements Comparator<MapObject>{
private final boolean en;
Collator collator = Collator.getInstance();
public CityComparator(boolean en){
public MapObjectComparator(boolean en){
this.en = en;
}
@Override
public int compare(City o1, City o2) {
public int compare(MapObject o1, MapObject o2) {
if(en){
return collator.compare(o1.getEnName(), o2.getEnName());
} else {

View file

@ -1518,7 +1518,7 @@ public class IndexCreator {
break;
}
}
progress.startTask("Searilizing city addresses...", j + (cities.size() - j) / 100);
progress.startTask("Searilizing city addresses...", j + ((cities.size() - j) / 100 + 1));
Map<String, Set<Street>> postcodes = new TreeMap<String, Set<Street>>();
boolean writeCities = true;
@ -1600,7 +1600,6 @@ public class IndexCreator {
writer.endWriteMapIndex();
writer.close();
} catch (RTreeException e) {
throw new IllegalStateException(e);
}
@ -2006,6 +2005,8 @@ public class IndexCreator {
addressConnection.close();
addressConnection = null;
}
writer.close();
log.info("Finish writing binary file");
}
@ -2048,15 +2049,15 @@ public class IndexCreator {
}
if(mapRAFile != null){
mapRAFile.close();
if (lastModifiedDate != null && mapFile.exists()) {
mapFile.setLastModified(lastModifiedDate);
}
}
if (mapConnection != null) {
mapConnection.commit();
mapConnection.close();
mapConnection = null;
if (lastModifiedDate != null && mapFile.exists()) {
mapFile.setLastModified(lastModifiedDate);
}
File tempDBFile = new File(workingDir, getTempMapDBFileName());
if(tempDBFile.exists()){
tempDBFile.delete();
@ -2133,7 +2134,7 @@ public class IndexCreator {
creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/belarus_nodes.tmp.odb"));
creator.generateIndexes(new File("e:/Information/OSM maps/belarus osm/belarus.osm.bz2"), new ConsoleProgressImplementation(3), null);
//
// creator.generateIndexes(new File("e:/Information/OSM maps/belarus osm/forest.osm"), new ConsoleProgressImplementation(3), null);

View file

@ -21,7 +21,6 @@ import net.osmand.osm.OSMSettings.OSMTagKey;
*/
public class MapRenderingTypes {
public static final int[] MAP_ZOOMS = null;
// TODO Internet access bits for point, polygon
/** standard schema :

View file

@ -14,6 +14,9 @@ message OsmAndStructure {
repeated OsmAndMapIndex mapIndex = 2;
// encoded as fixed32 length delimited
repeated OsmAndAddressIndex addressIndex = 3;
// last field should version again (to check consistency)
required uint32 versionConfirm = 32;
}
@ -74,7 +77,6 @@ message MapData {
}
/// ADDRESS INFORMATION TEST -----
message OsmAndAddressIndex {
@ -119,6 +121,8 @@ message CityIndex {
message PostcodeIndex {
required string postcode = 1;
required fixed32 x = 2; // x tile of 31 zoom
required fixed32 y = 3; // y tile of 31 zoom
repeated StreetIndex streets = 5;
}

View file

@ -1,53 +1,19 @@
package net.osmand;
import java.io.File;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.data.CityComparator;
import net.osmand.data.MapObject;
import net.osmand.data.PostCode;
import net.osmand.data.Street;
import net.osmand.data.City.CityType;
import net.osmand.data.index.IndexConstants;
import net.osmand.data.index.IndexConstants.IndexBuildingTable;
import net.osmand.data.index.IndexConstants.IndexCityTable;
import net.osmand.data.index.IndexConstants.IndexStreetNodeTable;
import net.osmand.data.index.IndexConstants.IndexStreetTable;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
import org.apache.commons.logging.Log;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class RegionAddressRepository {
private static final Log log = LogUtil.getLog(RegionAddressRepository.class);
private SQLiteDatabase db;
private String name;
private LinkedHashMap<Long, City> cities = new LinkedHashMap<Long, City>();
private Map<CityType, List<City>> cityTypes = new HashMap<CityType, List<City>>();
private Map<String, PostCode> postCodes = new TreeMap<String, PostCode>(Collator.getInstance());
private boolean useEnglishNames = false;
public interface RegionAddressRepository {
public static class MapObjectNameDistanceComparator implements Comparator<MapObject> {
@ -80,448 +46,43 @@ public class RegionAddressRepository {
}
public String getName();
public boolean initialize(final IProgress progress, File file) {
long start = System.currentTimeMillis();
if(db != null){
// close previous db
db.close();
}
db = SQLiteDatabase.openOrCreateDatabase(file, null);
name = file.getName().substring(0, file.getName().indexOf('.'));
if(db.getVersion() != IndexConstants.ADDRESS_TABLE_VERSION){
db.close();
db = null;
return false;
}
if (log.isDebugEnabled()) {
log.debug("Initializing address db " + file.getAbsolutePath() + " " + (System.currentTimeMillis() - start) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return true;
}
public PostCode getPostcode(String name);
public void close(){
clearCities();
if(db != null){
db.close();
}
}
public City getCityById(Long id);
public String getName() {
return name;
}
public Street getStreetByName(MapObject cityOrPostcode, String name);
public void clearCities(){
cities.clear();
cityTypes.clear();
postCodes.clear();
}
public Building getBuildingByName(Street street, String name);
public boolean areCitiesPreloaded(){
return !cities.isEmpty();
}
public boolean arePostcodesPreloaded(){
return !postCodes.isEmpty();
}
public boolean useEnglishNames();
public PostCode getPostcode(String name){
if(name == null){
return null;
}
preloadPostcodes();
return postCodes.get(name.toUpperCase());
}
public void setUseEnglishNames(boolean useEnglishNames);
public City getCityById(Long id){
if(id == -1){
// do not preload cities for that case
return null;
}
preloadCities();
return cities.get(id);
}
public void fillWithSuggestedBuildings(PostCode postcode, Street street, String name, List<Building> buildingsToFill);
public void fillWithSuggestedStreetsIntersectStreets(City city, Street st, List<Street> streetsToFill);
public void fillWithSuggestedStreets(MapObject cityOrPostcode, String name, List<Street> streetsToFill);
public void fillWithSuggestedCities(String name, List<MapObject> citiesToFill, LatLon currentLocation);
public LatLon findStreetIntersection(Street street, Street street2);
public boolean areCitiesPreloaded();
public boolean arePostcodesPreloaded();
public void addCityToPreloadedList(City city);
public Street getStreetByName(MapObject city, String name) {
preloadStreets(city);
if (city instanceof City) {
return ((City) city).getStreet(name);
} else {
return ((PostCode) city).getStreet(name);
}
}
public boolean isMapRepository();
public Building getBuildingByName(Street street, String name){
if(street.getBuildings().isEmpty()){
preloadBuildings(street);
}
for(Building b : street.getBuildings()){
String bName = useEnglishNames ? b.getEnName() : b.getName();
if(bName.equals(name)){
return b;
}
}
return null;
}
// is called on low memory
public void clearCache();
public boolean useEnglishNames(){
return useEnglishNames;
}
// called to close resources
public void close();
public void setUseEnglishNames(boolean useEnglishNames) {
this.useEnglishNames = useEnglishNames;
// sort streets
for (City c : cities.values()) {
if (!c.isEmptyWithStreets()) {
ArrayList<Street> list = new ArrayList<Street>(c.getStreets());
c.removeAllStreets();
for (Street s : list) {
c.registerStreet(s, useEnglishNames);
}
}
}
// sort cities
ArrayList<City> list = new ArrayList<City>(cities.values());
Collections.sort(list, new CityComparator(useEnglishNames));
cities.clear();
cityTypes.clear();
for(City c : list){
registerCity(c);
}
}
public void fillWithSuggestedBuildings(PostCode postcode, Street street, String name, List<Building> buildingsToFill){
preloadBuildings(street);
name = name.toLowerCase();
int ind = 0;
boolean empty = name.length() == 0;
if(empty && postcode == null){
buildingsToFill.addAll(street.getBuildings());
return;
}
for (Building building : street.getBuildings()) {
if(postcode != null && !postcode.getName().equals(building.getPostcode())){
continue;
} else if(empty){
buildingsToFill.add(building);
continue;
}
String bName = useEnglishNames ? building.getEnName() : building.getName();
String lowerCase = bName.toLowerCase();
if (lowerCase.startsWith(name)) {
buildingsToFill.add(ind, building);
ind++;
} else if (lowerCase.contains(name)) {
buildingsToFill.add(building);
}
}
}
public void fillWithSuggestedStreetsIntersectStreets(City city, Street st, List<Street> streetsToFill) {
if (st != null) {
Set<Long> strIds = new TreeSet<Long>();
log.debug("Start loading instersection streets for " + city.getName()); //$NON-NLS-1$
Cursor query = db.rawQuery("SELECT B.STREET FROM street_node A JOIN street_node B ON A.ID = B.ID WHERE A.STREET = ?", //$NON-NLS-1$
new String[] { st.getId() + "" }); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
if (st.getId() != query.getLong(0)) {
strIds.add(query.getLong(0));
}
} while (query.moveToNext());
}
query.close();
for (Street s : city.getStreets()) {
if (strIds.contains(s.getId())) {
streetsToFill.add(s);
}
}
log.debug("Loaded " + strIds.size() + " streets"); //$NON-NLS-1$ //$NON-NLS-2$
preloadWayNodes(st);
}
}
public void fillWithSuggestedStreets(MapObject o, String name, List<Street> streetsToFill){
assert o instanceof PostCode || o instanceof City;
City city = (City) (o instanceof City ? o : null);
PostCode post = (PostCode) (o instanceof PostCode ? o : null);
preloadStreets(o);
name = name.toLowerCase();
Collection<Street> streets = post == null ? city.getStreets() : post.getStreets() ;
int ind = 0;
if(name.length() == 0){
streetsToFill.addAll(streets);
return;
}
ind = 0;
for (Street s : streets) {
String sName = useEnglishNames ? s.getEnName() : s.getName();
String lowerCase = sName.toLowerCase();
if (lowerCase.startsWith(name)) {
streetsToFill.add(ind, s);
ind++;
} else if (lowerCase.contains(name)) {
streetsToFill.add(s);
}
}
}
public void fillWithSuggestedCities(String name, List<MapObject> citiesToFill, LatLon currentLocation){
preloadCities();
// essentially index is created that cities towns are first in cities map
int ind = 0;
if (name.length() >= 2 &&
Character.isDigit(name.charAt(0)) &&
Character.isDigit(name.charAt(1))) {
preloadPostcodes();
// also try to identify postcodes
String uName = name.toUpperCase();
for (String code : postCodes.keySet()) {
if (code.startsWith(uName)) {
citiesToFill.add(ind++, postCodes.get(code));
} else if(code.contains(uName)){
citiesToFill.add(postCodes.get(code));
}
}
}
if(name.length() < 3){
EnumSet<CityType> set = EnumSet.of(CityType.CITY, CityType.TOWN);
for(CityType t : set){
List<City> list = cityTypes.get(t);
if(list == null){
continue;
}
if(name.length() == 0){
citiesToFill.addAll(list);
} else {
name = name.toLowerCase();
for (City c : list) {
String cName = useEnglishNames ? c.getEnName() : c.getName();
String lowerCase = cName.toLowerCase();
if(lowerCase.startsWith(name)){
citiesToFill.add(c);
}
}
}
}
} else {
name = name.toLowerCase();
Collection<City> src = cities.values();
for (City c : src) {
String cName = useEnglishNames ? c.getEnName() : c.getName();
String lowerCase = cName.toLowerCase();
if (lowerCase.startsWith(name)) {
citiesToFill.add(ind, c);
ind++;
} else if (lowerCase.contains(name)) {
citiesToFill.add(c);
}
}
int initialsize = citiesToFill.size();
log.debug("Start loading cities for " +getName() + " filter " + name); //$NON-NLS-1$ //$NON-NLS-2$
// lower function in SQLite requires ICU extension
name = Algoritms.capitalizeFirstLetterAndLowercase(name);
int i = name.indexOf('\'');
if(i != -1){
// SQL quotation
name = name.replace("'", "''"); //$NON-NLS-1$ //$NON-NLS-2$
}
StringBuilder where = new StringBuilder(80);
where.
append(IndexCityTable.CITY_TYPE.toString()).append(" not in ("). //$NON-NLS-1$
append('\'').append(CityType.valueToString(CityType.CITY)).append('\'').append(", "). //$NON-NLS-1$
append('\'').append(CityType.valueToString(CityType.TOWN)).append('\'').append(") and "). //$NON-NLS-1$
append(useEnglishNames ? IndexCityTable.NAME_EN.toString() : IndexCityTable.NAME.toString()).append(" LIKE '"+name+"%'"); //$NON-NLS-1$ //$NON-NLS-2$
Cursor query = db.query(IndexCityTable.getTable(), IndexConstants.generateColumnNames(IndexCityTable.values()),
where.toString(), null, null, null, null);
if (query.moveToFirst()) {
List<City> hamlets = new ArrayList<City>();
do {
hamlets.add(parseCityFromCursor(query));
} while (query.moveToNext());
Collections.sort(hamlets, new MapObjectNameDistanceComparator(useEnglishNames, currentLocation));
citiesToFill.addAll(hamlets);
}
query.close();
log.debug("Loaded citites " + (citiesToFill.size() - initialsize)); //$NON-NLS-1$
}
}
public void preloadWayNodes(Street street){
if(street.getWayNodes().isEmpty()){
Cursor query = db.query(IndexStreetNodeTable.getTable(), IndexConstants.generateColumnNames(IndexStreetNodeTable.values()), "? = street", //$NON-NLS-1$
new String[] { street.getId() + "" }, null, null, null); //$NON-NLS-1$
log.debug("Start loading waynodes for " + street.getName()); //$NON-NLS-1$
Map<Long, Way> ways = new LinkedHashMap<Long, Way>();
if (query.moveToFirst()) {
do {
Node n = new Node(query.getDouble(IndexStreetNodeTable.LATITUDE.ordinal()),
query.getDouble(IndexBuildingTable.LONGITUDE.ordinal()),
query.getLong(IndexStreetNodeTable.ID.ordinal()));
long way = query.getLong(IndexStreetNodeTable.WAY.ordinal());
if(!ways.containsKey(way)){
ways.put(way, new Way(way));
}
ways.get(way).addNode(n);
} while (query.moveToNext());
}
query.close();
for(Way w : ways.values()){
street.getWayNodes().add(w);
}
log.debug("Loaded " + ways.size() + " ways"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void preloadPostcodes() {
if (postCodes.isEmpty()) {
// check if it possible to load postcodes
Cursor query = db.query(true, IndexBuildingTable.getTable(), new String[] { IndexBuildingTable.POSTCODE.toString() }, null,
null, null, null, null, null);
log.debug("Start loading postcodes for "); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
String postcode = query.getString(0);
if (postcode != null) {
postCodes.put(postcode, new PostCode(postcode));
}
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " + postCodes.size() + " postcodes "); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void preloadBuildings(Street street){
if (street.getBuildings().isEmpty()) {
Cursor query = db.query(IndexBuildingTable.getTable(), IndexConstants.generateColumnNames(IndexBuildingTable.values()), "? = street", //$NON-NLS-1$
new String[] { street.getId() + "" }, null, null, null); //$NON-NLS-1$
log.debug("Start loading buildings for " + street.getName()); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
Building building = new Building();
building.setId(query.getLong(IndexBuildingTable.ID.ordinal()));
building.setLocation(query.getDouble(IndexBuildingTable.LATITUDE.ordinal()), query.getDouble(IndexBuildingTable.LONGITUDE
.ordinal()));
building.setName(query.getString(IndexBuildingTable.NAME.ordinal()));
building.setEnName(query.getString(IndexBuildingTable.NAME_EN.ordinal()));
building.setPostcode(query.getString(IndexBuildingTable.POSTCODE.ordinal()));
street.registerBuilding(building);
} while (query.moveToNext());
street.sortBuildings();
}
query.close();
log.debug("Loaded " + street.getBuildings().size() + " buildings"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void preloadStreets(MapObject o){
assert o instanceof PostCode || o instanceof City;
City city = (City) (o instanceof City ? o : null);
PostCode post = (PostCode) (o instanceof PostCode ? o : null);
if (city != null && city.isEmptyWithStreets()) {
log.debug("Start loading streets for " + city.getName()); //$NON-NLS-1$
Cursor query = db.query(IndexStreetTable.getTable(), IndexConstants.generateColumnNames(IndexStreetTable.values()), "? = city", //$NON-NLS-1$
new String[] { city.getId() + "" }, null, null, null); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
Street street = new Street(city);
street.setId(query.getLong(IndexStreetTable.ID.ordinal()));
street.setLocation(query.getDouble(IndexStreetTable.LATITUDE.ordinal()), query.getDouble(IndexStreetTable.LONGITUDE.ordinal()));
street.setName(query.getString(IndexStreetTable.NAME.ordinal()));
street.setEnName(query.getString(IndexStreetTable.NAME_EN.ordinal()));
city.registerStreet(street, useEnglishNames);
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " + city.getStreets().size() + " streets"); //$NON-NLS-1$ //$NON-NLS-2$
} else if(post != null && post.isEmptyWithStreets()){
log.debug("Start loading streets for " + post.getName()); //$NON-NLS-1$
Cursor query = db.rawQuery("SELECT B.CITY, B.ID,B.LATITUDE, B.LONGITUDE, B.NAME, B.NAME_EN FROM building A JOIN street B ON A.street = B.ID WHERE A.postcode = ?", //$NON-NLS-1$
new String[] { post.getName() + "" }); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
city = getCityById(query.getLong(0));
Street street = null;
if(city != null){
preloadStreets(city);
street = city.getStreet(useEnglishNames ? query.getString(5) : query.getString(4));
}
if(street == null){
street = new Street(city);
street.setId(query.getLong(1));
street.setLocation(query.getDouble(2), query.getDouble(3));
street.setName(query.getString(4));
street.setEnName(query.getString(5));
if(city != null){
city.registerStreet(street, useEnglishNames);
}
}
post.registerStreet(street, useEnglishNames);
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " +post.getStreets().size() + " streets"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void registerCity(City city){
cities.put(city.getId(), city);
if(!cityTypes.containsKey(city.getType())){
cityTypes.put(city.getType(), new ArrayList<City>());
}
cityTypes.get(city.getType()).add(city);
}
protected City parseCityFromCursor(Cursor query){
CityType type = CityType.valueFromString(query.getString(IndexCityTable.CITY_TYPE.ordinal()));
if (type != null) {
City city = new City(type);
city.setId(query.getLong(IndexCityTable.ID.ordinal()));
city.setLocation(query.getDouble(IndexCityTable.LATITUDE.ordinal()),
query.getDouble(IndexCityTable.LONGITUDE.ordinal()));
city.setName(query.getString(IndexCityTable.NAME.ordinal()));
city.setEnName(query.getString(IndexCityTable.NAME_EN.ordinal()));
return city;
}
return null;
}
public void preloadCities(){
if (cities.isEmpty()) {
log.debug("Start loading cities for " +getName()); //$NON-NLS-1$
StringBuilder where = new StringBuilder();
where.append(IndexCityTable.CITY_TYPE.toString()).append('=').
append('\'').append(CityType.valueToString(CityType.CITY)).append('\'').append(" or "). //$NON-NLS-1$
append(IndexCityTable.CITY_TYPE.toString()).append('=').
append('\'').append(CityType.valueToString(CityType.TOWN)).append('\'');
Cursor query = db.query(IndexCityTable.getTable(), IndexConstants.generateColumnNames(IndexCityTable.values()),
where.toString(), null, null, null, null);
if(query.moveToFirst()){
do {
City city = parseCityFromCursor(query);
if (city != null) {
cities.put(city.getId(), city);
if(!cityTypes.containsKey(city.getType())){
cityTypes.put(city.getType(), new ArrayList<City>());
}
cityTypes.get(city.getType()).add(city);
}
} while(query.moveToNext());
}
log.debug("Loaded " + cities.size() + " cities"); //$NON-NLS-1$ //$NON-NLS-2$
query.close();
}
}
}

View file

@ -0,0 +1,325 @@
package net.osmand;
import java.io.IOException;
import java.text.Collator;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.data.MapObject;
import net.osmand.data.MapObjectComparator;
import net.osmand.data.PostCode;
import net.osmand.data.Street;
import net.osmand.osm.LatLon;
import org.apache.commons.logging.Log;
public class RegionAddressRepositoryBinary implements RegionAddressRepository {
private static final Log log = LogUtil.getLog(RegionAddressRepositoryBinary.class);
private BinaryMapIndexReader file;
private String region;
private LinkedHashMap<Long, City> cities = new LinkedHashMap<Long, City>();
private Map<String, PostCode> postCodes = new TreeMap<String, PostCode>(Collator.getInstance());
private boolean useEnglishNames = false;
private Comparator<MapObject> comparator = new MapObjectComparator(useEnglishNames);
public RegionAddressRepositoryBinary(BinaryMapIndexReader file, String name) {
this.file = file;
this.region = name;
}
public void close(){
this.file = null;
}
@Override
public boolean isMapRepository() {
return true;
}
@Override
public void fillWithSuggestedBuildings(PostCode postcode, Street street, String name, List<Building> buildingsToFill) {
preloadBuildings(street);
if(name.length() == 0){
buildingsToFill.addAll(street.getBuildings());
return;
}
name = name.toLowerCase();
int ind = 0;
for (Building building : street.getBuildings()) {
String bName = useEnglishNames ? building.getEnName() : building.getName();
String lowerCase = bName.toLowerCase();
if (lowerCase.startsWith(name)) {
buildingsToFill.add(ind, building);
ind++;
} else if (lowerCase.contains(name)) {
buildingsToFill.add(building);
}
}
Collections.sort(buildingsToFill, comparator);
}
private void preloadBuildings(Street street) {
if(street.getBuildings().isEmpty()){
try {
file.preloadBuildings(street);
} catch (IOException e) {
log.error("Disk operation failed" , e); //$NON-NLS-1$
}
}
}
@Override
public void fillWithSuggestedStreets(MapObject o, String name, List<Street> streetsToFill) {
assert o instanceof PostCode || o instanceof City;
City city = (City) (o instanceof City ? o : null);
PostCode post = (PostCode) (o instanceof PostCode ? o : null);
preloadStreets(o);
name = name.toLowerCase();
Collection<Street> streets = post == null ? city.getStreets() : post.getStreets() ;
if(name.length() == 0){
streetsToFill.addAll(streets);
} else {
int ind = 0;
for (Street s : streets) {
String sName = useEnglishNames ? s.getEnName() : s.getName();
String lowerCase = sName.toLowerCase();
if (lowerCase.startsWith(name)) {
streetsToFill.add(ind, s);
ind++;
} else if (lowerCase.contains(name)) {
streetsToFill.add(s);
}
}
}
Collections.sort(streetsToFill, comparator);
}
private void preloadStreets(MapObject o) {
assert o instanceof PostCode || o instanceof City;
try {
if(o instanceof PostCode){
file.preloadStreets((PostCode) o);
} else {
file.preloadStreets((City) o);
}
} catch (IOException e) {
log.error("Disk operation failed" , e); //$NON-NLS-1$
}
}
@Override
public void fillWithSuggestedCities(String name, List<MapObject> citiesToFill, LatLon currentLocation) {
preloadCities();
try {
// essentially index is created that cities towns are first in cities map
int ind = 0;
if (name.length() >= 2 &&
Character.isDigit(name.charAt(0)) &&
Character.isDigit(name.charAt(1))) {
// also try to identify postcodes
String uName = name.toUpperCase();
for (PostCode code : file.getPostcodes(region)) {
if (code.getName().startsWith(uName)) {
citiesToFill.add(ind++, code);
} else if(code.getName().contains(uName)){
citiesToFill.add(code);
}
}
}
if (name.length() < 3) {
if (name.length() == 0) {
citiesToFill.addAll(cities.values());
} else {
name = name.toLowerCase();
for (City c : cities.values()) {
String cName = useEnglishNames ? c.getEnName() : c.getName();
String lowerCase = cName.toLowerCase();
if (lowerCase.startsWith(name)) {
citiesToFill.add(c);
}
}
}
} else {
name = name.toLowerCase();
Collection<City> src = cities.values();
for (City c : src) {
String cName = useEnglishNames ? c.getEnName() : c.getName();
String lowerCase = cName.toLowerCase();
if (lowerCase.startsWith(name)) {
citiesToFill.add(ind, c);
ind++;
} else if (lowerCase.contains(name)) {
citiesToFill.add(c);
}
}
int initialsize = citiesToFill.size();
for(City c : file.getVillages(name)){
String cName = useEnglishNames ? c.getEnName() : c.getName();
String lowerCase = cName.toLowerCase();
if (lowerCase.startsWith(name)) {
citiesToFill.add(ind, c);
ind++;
} else if (lowerCase.contains(name)) {
citiesToFill.add(c);
}
}
log.debug("Loaded citites " + (citiesToFill.size() - initialsize)); //$NON-NLS-1$
}
} catch (IOException e) {
log.error("Disk operation failed" , e); //$NON-NLS-1$
}
}
@Override
public void fillWithSuggestedStreetsIntersectStreets(City city, Street st, List<Street> streetsToFill) {
// TODO Auto-generated method stub
}
@Override
public LatLon findStreetIntersection(Street street, Street street2) {
// TODO Auto-generated method stub
return null;
}
@Override
public Building getBuildingByName(Street street, String name) {
preloadBuildings(street);
for (Building b : street.getBuildings()) {
String bName = useEnglishNames ? b.getEnName() : b.getName();
if (bName.equals(name)) {
return b;
}
}
return null;
}
@Override
public String getName() {
return region;
}
@Override
public boolean useEnglishNames() {
return useEnglishNames;
}
@Override
public City getCityById(Long id) {
if(id == -1){
// do not preload cities for that case
return null;
}
preloadCities();
return cities.get(id);
}
private void preloadCities() {
if (cities.isEmpty()) {
try {
List<City> cs = file.getCities(region);
for (City c : cs) {
cities.put(c.getId(), c);
}
} catch (IOException e) {
log.error("Disk operation failed", e); //$NON-NLS-1$
}
}
}
@Override
public PostCode getPostcode(String name) {
if(name == null){
return null;
}
String uc = name.toUpperCase();
if(!postCodes.containsKey(uc)){
try {
postCodes.put(uc, file.getPostcodeByName(this.region, name));
} catch (IOException e) {
log.error("Disk operation failed", e); //$NON-NLS-1$
}
}
return postCodes.get(uc);
}
@Override
public Street getStreetByName(MapObject o, String name) {
assert o instanceof PostCode || o instanceof City;
City city = (City) (o instanceof City ? o : null);
PostCode post = (PostCode) (o instanceof PostCode ? o : null);
preloadStreets(o);
name = name.toLowerCase();
Collection<Street> streets = post == null ? city.getStreets() : post.getStreets();
for (Street s : streets) {
String sName = useEnglishNames ? s.getEnName() : s.getName();
String lowerCase = sName.toLowerCase();
if (lowerCase.equals(name)) {
return s;
}
}
return null;
}
@Override
public void setUseEnglishNames(boolean useEnglishNames) {
this.useEnglishNames = useEnglishNames;
this.comparator = new MapObjectComparator(useEnglishNames);
}
@Override
public void addCityToPreloadedList(City city) {
cities.put(city.getId(), city);
}
@Override
public boolean areCitiesPreloaded() {
return !cities.isEmpty();
}
@Override
public boolean arePostcodesPreloaded() {
// postcodes are always preloaded
// do not load them into memory (just cache last used)
return true;
}
@Override
public void clearCache() {
cities.clear();
postCodes.clear();
}
}

View file

@ -0,0 +1,524 @@
package net.osmand;
import java.io.File;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.data.MapObject;
import net.osmand.data.MapObjectComparator;
import net.osmand.data.PostCode;
import net.osmand.data.Street;
import net.osmand.data.City.CityType;
import net.osmand.data.index.IndexConstants;
import net.osmand.data.index.IndexConstants.IndexBuildingTable;
import net.osmand.data.index.IndexConstants.IndexCityTable;
import net.osmand.data.index.IndexConstants.IndexStreetNodeTable;
import net.osmand.data.index.IndexConstants.IndexStreetTable;
import net.osmand.osm.LatLon;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
import org.apache.commons.logging.Log;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class RegionAddressRepositoryOdb implements RegionAddressRepository {
private static final Log log = LogUtil.getLog(RegionAddressRepositoryOdb.class);
private SQLiteDatabase db;
private String name;
private LinkedHashMap<Long, City> cities = new LinkedHashMap<Long, City>();
private Map<CityType, List<City>> cityTypes = new HashMap<CityType, List<City>>();
private Map<String, PostCode> postCodes = new TreeMap<String, PostCode>(Collator.getInstance());
private boolean useEnglishNames = false;
public boolean initialize(final IProgress progress, File file) {
long start = System.currentTimeMillis();
if(db != null){
// close previous db
db.close();
}
db = SQLiteDatabase.openOrCreateDatabase(file, null);
// add * as old format
name = file.getName().substring(0, file.getName().indexOf('.'))+" *"; //$NON-NLS-1$
if(db.getVersion() != IndexConstants.ADDRESS_TABLE_VERSION){
db.close();
db = null;
return false;
}
if (log.isDebugEnabled()) {
log.debug("Initializing address db " + file.getAbsolutePath() + " " + (System.currentTimeMillis() - start) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return true;
}
public void close(){
clearCities();
if(db != null){
db.close();
}
}
public String getName() {
return name;
}
public void clearCities(){
cities.clear();
cityTypes.clear();
postCodes.clear();
}
public boolean areCitiesPreloaded(){
return !cities.isEmpty();
}
public boolean arePostcodesPreloaded(){
return !postCodes.isEmpty();
}
public PostCode getPostcode(String name){
if(name == null){
return null;
}
preloadPostcodes();
return postCodes.get(name.toUpperCase());
}
public City getCityById(Long id){
if(id == -1){
// do not preload cities for that case
return null;
}
preloadCities();
return cities.get(id);
}
public Street getStreetByName(MapObject city, String name) {
preloadStreets(city);
if (city instanceof City) {
return ((City) city).getStreet(name);
} else {
return ((PostCode) city).getStreet(name);
}
}
public Building getBuildingByName(Street street, String name){
if(street.getBuildings().isEmpty()){
preloadBuildings(street);
}
for(Building b : street.getBuildings()){
String bName = useEnglishNames ? b.getEnName() : b.getName();
if(bName.equals(name)){
return b;
}
}
return null;
}
public boolean useEnglishNames(){
return useEnglishNames;
}
public void setUseEnglishNames(boolean useEnglishNames) {
this.useEnglishNames = useEnglishNames;
// sort streets
for (City c : cities.values()) {
if (!c.isEmptyWithStreets()) {
ArrayList<Street> list = new ArrayList<Street>(c.getStreets());
c.removeAllStreets();
for (Street s : list) {
c.registerStreet(s, useEnglishNames);
}
}
}
// sort cities
ArrayList<City> list = new ArrayList<City>(cities.values());
Collections.sort(list, new MapObjectComparator(useEnglishNames));
cities.clear();
cityTypes.clear();
for(City c : list){
addCityToPreloadedList(c);
}
}
public void fillWithSuggestedBuildings(PostCode postcode, Street street, String name, List<Building> buildingsToFill){
preloadBuildings(street);
name = name.toLowerCase();
int ind = 0;
boolean empty = name.length() == 0;
if(empty && postcode == null){
buildingsToFill.addAll(street.getBuildings());
return;
}
for (Building building : street.getBuildings()) {
if(postcode != null && !postcode.getName().equals(building.getPostcode())){
continue;
} else if(empty){
buildingsToFill.add(building);
continue;
}
String bName = useEnglishNames ? building.getEnName() : building.getName();
String lowerCase = bName.toLowerCase();
if (lowerCase.startsWith(name)) {
buildingsToFill.add(ind, building);
ind++;
} else if (lowerCase.contains(name)) {
buildingsToFill.add(building);
}
}
}
public void fillWithSuggestedStreetsIntersectStreets(City city, Street st, List<Street> streetsToFill) {
if (st != null) {
Set<Long> strIds = new TreeSet<Long>();
log.debug("Start loading instersection streets for " + city.getName()); //$NON-NLS-1$
Cursor query = db.rawQuery("SELECT B.STREET FROM street_node A JOIN street_node B ON A.ID = B.ID WHERE A.STREET = ?", //$NON-NLS-1$
new String[] { st.getId() + "" }); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
if (st.getId() != query.getLong(0)) {
strIds.add(query.getLong(0));
}
} while (query.moveToNext());
}
query.close();
for (Street s : city.getStreets()) {
if (strIds.contains(s.getId())) {
streetsToFill.add(s);
}
}
log.debug("Loaded " + strIds.size() + " streets"); //$NON-NLS-1$ //$NON-NLS-2$
preloadWayNodes(st);
}
}
public void fillWithSuggestedStreets(MapObject o, String name, List<Street> streetsToFill){
assert o instanceof PostCode || o instanceof City;
City city = (City) (o instanceof City ? o : null);
PostCode post = (PostCode) (o instanceof PostCode ? o : null);
preloadStreets(o);
name = name.toLowerCase();
Collection<Street> streets = post == null ? city.getStreets() : post.getStreets() ;
int ind = 0;
if(name.length() == 0){
streetsToFill.addAll(streets);
return;
}
ind = 0;
for (Street s : streets) {
String sName = useEnglishNames ? s.getEnName() : s.getName();
String lowerCase = sName.toLowerCase();
if (lowerCase.startsWith(name)) {
streetsToFill.add(ind, s);
ind++;
} else if (lowerCase.contains(name)) {
streetsToFill.add(s);
}
}
}
public void fillWithSuggestedCities(String name, List<MapObject> citiesToFill, LatLon currentLocation){
preloadCities();
// essentially index is created that cities towns are first in cities map
int ind = 0;
if (name.length() >= 2 &&
Character.isDigit(name.charAt(0)) &&
Character.isDigit(name.charAt(1))) {
preloadPostcodes();
// also try to identify postcodes
String uName = name.toUpperCase();
for (String code : postCodes.keySet()) {
if (code.startsWith(uName)) {
citiesToFill.add(ind++, postCodes.get(code));
} else if(code.contains(uName)){
citiesToFill.add(postCodes.get(code));
}
}
}
if(name.length() < 3){
EnumSet<CityType> set = EnumSet.of(CityType.CITY, CityType.TOWN);
for(CityType t : set){
List<City> list = cityTypes.get(t);
if(list == null){
continue;
}
if(name.length() == 0){
citiesToFill.addAll(list);
} else {
name = name.toLowerCase();
for (City c : list) {
String cName = useEnglishNames ? c.getEnName() : c.getName();
String lowerCase = cName.toLowerCase();
if(lowerCase.startsWith(name)){
citiesToFill.add(c);
}
}
}
}
} else {
name = name.toLowerCase();
Collection<City> src = cities.values();
for (City c : src) {
String cName = useEnglishNames ? c.getEnName() : c.getName();
String lowerCase = cName.toLowerCase();
if (lowerCase.startsWith(name)) {
citiesToFill.add(ind, c);
ind++;
} else if (lowerCase.contains(name)) {
citiesToFill.add(c);
}
}
int initialsize = citiesToFill.size();
log.debug("Start loading cities for " +getName() + " filter " + name); //$NON-NLS-1$ //$NON-NLS-2$
// lower function in SQLite requires ICU extension
name = Algoritms.capitalizeFirstLetterAndLowercase(name);
int i = name.indexOf('\'');
if(i != -1){
// SQL quotation
name = name.replace("'", "''"); //$NON-NLS-1$ //$NON-NLS-2$
}
StringBuilder where = new StringBuilder(80);
where.
append(IndexCityTable.CITY_TYPE.toString()).append(" not in ("). //$NON-NLS-1$
append('\'').append(CityType.valueToString(CityType.CITY)).append('\'').append(", "). //$NON-NLS-1$
append('\'').append(CityType.valueToString(CityType.TOWN)).append('\'').append(") and "). //$NON-NLS-1$
append(useEnglishNames ? IndexCityTable.NAME_EN.toString() : IndexCityTable.NAME.toString()).append(" LIKE '"+name+"%'"); //$NON-NLS-1$ //$NON-NLS-2$
Cursor query = db.query(IndexCityTable.getTable(), IndexConstants.generateColumnNames(IndexCityTable.values()),
where.toString(), null, null, null, null);
if (query.moveToFirst()) {
List<City> hamlets = new ArrayList<City>();
do {
hamlets.add(parseCityFromCursor(query));
} while (query.moveToNext());
Collections.sort(hamlets, new MapObjectNameDistanceComparator(useEnglishNames, currentLocation));
citiesToFill.addAll(hamlets);
}
query.close();
log.debug("Loaded citites " + (citiesToFill.size() - initialsize)); //$NON-NLS-1$
}
}
public void preloadWayNodes(Street street){
if(street.getWayNodes().isEmpty()){
Cursor query = db.query(IndexStreetNodeTable.getTable(), IndexConstants.generateColumnNames(IndexStreetNodeTable.values()), "? = street", //$NON-NLS-1$
new String[] { street.getId() + "" }, null, null, null); //$NON-NLS-1$
log.debug("Start loading waynodes for " + street.getName()); //$NON-NLS-1$
Map<Long, Way> ways = new LinkedHashMap<Long, Way>();
if (query.moveToFirst()) {
do {
Node n = new Node(query.getDouble(IndexStreetNodeTable.LATITUDE.ordinal()),
query.getDouble(IndexBuildingTable.LONGITUDE.ordinal()),
query.getLong(IndexStreetNodeTable.ID.ordinal()));
long way = query.getLong(IndexStreetNodeTable.WAY.ordinal());
if(!ways.containsKey(way)){
ways.put(way, new Way(way));
}
ways.get(way).addNode(n);
} while (query.moveToNext());
}
query.close();
for(Way w : ways.values()){
street.getWayNodes().add(w);
}
log.debug("Loaded " + ways.size() + " ways"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void preloadPostcodes() {
if (postCodes.isEmpty()) {
// check if it possible to load postcodes
Cursor query = db.query(true, IndexBuildingTable.getTable(), new String[] { IndexBuildingTable.POSTCODE.toString() }, null,
null, null, null, null, null);
log.debug("Start loading postcodes for "); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
String postcode = query.getString(0);
if (postcode != null) {
postCodes.put(postcode, new PostCode(postcode));
}
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " + postCodes.size() + " postcodes "); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void preloadBuildings(Street street){
if (street.getBuildings().isEmpty()) {
Cursor query = db.query(IndexBuildingTable.getTable(), IndexConstants.generateColumnNames(IndexBuildingTable.values()), "? = street", //$NON-NLS-1$
new String[] { street.getId() + "" }, null, null, null); //$NON-NLS-1$
log.debug("Start loading buildings for " + street.getName()); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
Building building = new Building();
building.setId(query.getLong(IndexBuildingTable.ID.ordinal()));
building.setLocation(query.getDouble(IndexBuildingTable.LATITUDE.ordinal()), query.getDouble(IndexBuildingTable.LONGITUDE
.ordinal()));
building.setName(query.getString(IndexBuildingTable.NAME.ordinal()));
building.setEnName(query.getString(IndexBuildingTable.NAME_EN.ordinal()));
building.setPostcode(query.getString(IndexBuildingTable.POSTCODE.ordinal()));
street.registerBuilding(building);
} while (query.moveToNext());
street.sortBuildings();
}
query.close();
log.debug("Loaded " + street.getBuildings().size() + " buildings"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void preloadStreets(MapObject o){
assert o instanceof PostCode || o instanceof City;
City city = (City) (o instanceof City ? o : null);
PostCode post = (PostCode) (o instanceof PostCode ? o : null);
if (city != null && city.isEmptyWithStreets()) {
log.debug("Start loading streets for " + city.getName()); //$NON-NLS-1$
Cursor query = db.query(IndexStreetTable.getTable(), IndexConstants.generateColumnNames(IndexStreetTable.values()), "? = city", //$NON-NLS-1$
new String[] { city.getId() + "" }, null, null, null); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
Street street = new Street(city);
street.setId(query.getLong(IndexStreetTable.ID.ordinal()));
street.setLocation(query.getDouble(IndexStreetTable.LATITUDE.ordinal()), query.getDouble(IndexStreetTable.LONGITUDE.ordinal()));
street.setName(query.getString(IndexStreetTable.NAME.ordinal()));
street.setEnName(query.getString(IndexStreetTable.NAME_EN.ordinal()));
city.registerStreet(street, useEnglishNames);
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " + city.getStreets().size() + " streets"); //$NON-NLS-1$ //$NON-NLS-2$
} else if(post != null && post.isEmptyWithStreets()){
log.debug("Start loading streets for " + post.getName()); //$NON-NLS-1$
Cursor query = db.rawQuery("SELECT B.CITY, B.ID,B.LATITUDE, B.LONGITUDE, B.NAME, B.NAME_EN FROM building A JOIN street B ON A.street = B.ID WHERE A.postcode = ?", //$NON-NLS-1$
new String[] { post.getName() + "" }); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
city = getCityById(query.getLong(0));
Street street = null;
if(city != null){
preloadStreets(city);
street = city.getStreet(useEnglishNames ? query.getString(5) : query.getString(4));
}
if(street == null){
street = new Street(city);
street.setId(query.getLong(1));
street.setLocation(query.getDouble(2), query.getDouble(3));
street.setName(query.getString(4));
street.setEnName(query.getString(5));
if(city != null){
city.registerStreet(street, useEnglishNames);
}
}
post.registerStreet(street, useEnglishNames);
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " +post.getStreets().size() + " streets"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void addCityToPreloadedList(City city){
cities.put(city.getId(), city);
if(!cityTypes.containsKey(city.getType())){
cityTypes.put(city.getType(), new ArrayList<City>());
}
cityTypes.get(city.getType()).add(city);
}
protected City parseCityFromCursor(Cursor query){
CityType type = CityType.valueFromString(query.getString(IndexCityTable.CITY_TYPE.ordinal()));
if (type != null) {
City city = new City(type);
city.setId(query.getLong(IndexCityTable.ID.ordinal()));
city.setLocation(query.getDouble(IndexCityTable.LATITUDE.ordinal()),
query.getDouble(IndexCityTable.LONGITUDE.ordinal()));
city.setName(query.getString(IndexCityTable.NAME.ordinal()));
city.setEnName(query.getString(IndexCityTable.NAME_EN.ordinal()));
return city;
}
return null;
}
public void preloadCities(){
if (cities.isEmpty()) {
log.debug("Start loading cities for " +getName()); //$NON-NLS-1$
StringBuilder where = new StringBuilder();
where.append(IndexCityTable.CITY_TYPE.toString()).append('=').
append('\'').append(CityType.valueToString(CityType.CITY)).append('\'').append(" or "). //$NON-NLS-1$
append(IndexCityTable.CITY_TYPE.toString()).append('=').
append('\'').append(CityType.valueToString(CityType.TOWN)).append('\'');
Cursor query = db.query(IndexCityTable.getTable(), IndexConstants.generateColumnNames(IndexCityTable.values()),
where.toString(), null, null, null, null);
if(query.moveToFirst()){
do {
City city = parseCityFromCursor(query);
if (city != null) {
cities.put(city.getId(), city);
if(!cityTypes.containsKey(city.getType())){
cityTypes.put(city.getType(), new ArrayList<City>());
}
cityTypes.get(city.getType()).add(city);
}
} while(query.moveToNext());
}
log.debug("Loaded " + cities.size() + " cities"); //$NON-NLS-1$ //$NON-NLS-2$
query.close();
}
}
@Override
public boolean isMapRepository() {
return false;
}
@Override
public void clearCache() {
clearCities();
}
@Override
public LatLon findStreetIntersection(Street street, Street street2) {
preloadWayNodes(street2);
preloadWayNodes(street);
for(Way w : street2.getWayNodes()){
for(Way w2 : street.getWayNodes()){
for(Node n : w.getNodes()){
for(Node n2 : w2.getNodes()){
if(n.getId() == n2.getId()){
return n.getLatLon();
}
}
}
}
}
return null;
}
}

View file

@ -13,6 +13,7 @@ import java.util.Stack;
import java.util.TreeMap;
import net.osmand.activities.OsmandApplication;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.Amenity;
import net.osmand.data.TransportStop;
import net.osmand.data.index.IndexConstants;
@ -367,9 +368,15 @@ public class ResourceManager {
if (f.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) {
progress.startTask(Messages.getMessage("indexing_map") + f.getName(), -1); //$NON-NLS-1$
try {
boolean initialized = renderer.initializeNewResource(progress, f);
if (!initialized) {
BinaryMapIndexReader index = renderer.initializeNewResource(progress, f);
if (index == null) {
warnings.add(MessageFormat.format(Messages.getMessage("version_index_is_not_supported"), f.getName())); //$NON-NLS-1$
} else {
for(String rName : index.getRegionNames()) {
// skip duplicate names (don't make collision between getName() and name in the map)
RegionAddressRepositoryBinary rarb = new RegionAddressRepositoryBinary(index, rName);
addressMap.put(rName, rarb);
}
}
} catch (SQLiteException e) {
log.error("Exception reading " + f.getAbsolutePath(), e); //$NON-NLS-1$
@ -430,7 +437,7 @@ public class ResourceManager {
public void indexingAddress(final IProgress progress, List<String> warnings, File f) {
if (f.getName().endsWith(IndexConstants.ADDRESS_INDEX_EXT)) {
RegionAddressRepository repository = new RegionAddressRepository();
RegionAddressRepositoryOdb repository = new RegionAddressRepositoryOdb();
progress.startTask(Messages.getMessage("indexing_address") + f.getName(), -1); //$NON-NLS-1$
try {
boolean initialized = repository.initialize(progress, f);
@ -630,7 +637,7 @@ public class ResourceManager {
r.clearCache();
}
for(RegionAddressRepository r : addressMap.values()){
r.clearCities();
r.clearCache();
}
renderer.clearCache();

View file

@ -14,8 +14,6 @@ import net.osmand.data.MapObject;
import net.osmand.data.PostCode;
import net.osmand.data.Street;
import net.osmand.osm.LatLon;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
@ -179,23 +177,8 @@ public class SearchAddressActivity extends Activity {
int zoom = 12;
boolean en = OsmandSettings.usingEnglishNames(OsmandSettings.getPrefs(this));
if (street2 != null && street != null) {
region.preloadWayNodes(street2);
region.preloadWayNodes(street);
Node inters = null;
for(Way w : street2.getWayNodes()){
for(Way w2 : street.getWayNodes()){
for(Node n : w.getNodes()){
for(Node n2 : w2.getNodes()){
if(n.getId() == n2.getId()){
inters = n;
break;
}
}
}
}
}
if(inters != null){
l = inters.getLatLon();
l = region.findStreetIntersection(street, street2);
if(l != null) {
String cityName = postcode != null? postcode.getName() : city.getName(en);
historyName = MessageFormat.format(getString(R.string.search_history_int_streets),
street.getName(en), street2.getName(en), cityName);
@ -386,21 +369,5 @@ public class SearchAddressActivity extends Activity {
}
}
@Override
protected void onPause() {
// Do not reset settings (cause it is not so necessary)
// if(building == null && OsmandSettings.getLastSearchedBuilding(this).length() > 0){
// OsmandSettings.setLastSearchedBuilding(this, "");
// }
// if(street == null && OsmandSettings.getLastSearchedStreet(this).length() > 0){
// OsmandSettings.setLastSearchedStreet(this, "");
// }
// if(city == null && OsmandSettings.getLastSearchedCity(this) != -1){
// OsmandSettings.setLastSearchedCity(this, -1l);
// }
super.onPause();
}
}

View file

@ -52,7 +52,7 @@ public class SearchCityByNameActivity extends SearchByNameAbstractActivity<MapOb
if (obj instanceof City) {
OsmandSettings.setLastSearchedCity(this, obj.getId());
if (region.getCityById(obj.getId()) == null) {
region.registerCity((City) obj);
region.addCityToPreloadedList((City) obj);
}
} else if(obj instanceof PostCode){
OsmandSettings.setLastSearchedPostcode(this, obj.getName());

View file

@ -74,34 +74,35 @@ public class MapRenderRepositories {
}
public boolean initializeNewResource(final IProgress progress, File file) {
public BinaryMapIndexReader initializeNewResource(final IProgress progress, File file) {
long start = System.currentTimeMillis();
if(files.containsKey(file.getAbsolutePath())){
closeConnection(files.get(file.getAbsolutePath()), file.getAbsolutePath());
}
RandomAccessFile raf = null;
BinaryMapIndexReader reader = null;
try {
raf = new RandomAccessFile(file, "r"); //$NON-NLS-1$
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
reader = new BinaryMapIndexReader(raf);
if(reader.getVersion() != IndexConstants.BINARY_MAP_VERSION){
return false;
return null;
}
files.put(file.getAbsolutePath(), reader);
} catch (IOException e) {
log.error("No connection", e); //$NON-NLS-1$
log.error("No connection or unsupported version", e); //$NON-NLS-1$
if(raf != null){
try {
raf.close();
} catch (IOException e1) {
}
}
return false;
return null;
}
if (log.isDebugEnabled()) {
log.debug("Initializing db " + file.getAbsolutePath() + " " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return true;
return reader;
}