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:
parent
425d0d1fcc
commit
ac495120d9
15 changed files with 1296 additions and 609 deletions
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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 {
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
325
OsmAnd/src/net/osmand/RegionAddressRepositoryBinary.java
Normal file
325
OsmAnd/src/net/osmand/RegionAddressRepositoryBinary.java
Normal 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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
524
OsmAnd/src/net/osmand/RegionAddressRepositoryOdb.java
Normal file
524
OsmAnd/src/net/osmand/RegionAddressRepositoryOdb.java
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue