initial import
git-svn-id: https://osmand.googlecode.com/svn/trunk@3 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
24df06a387
commit
2b43c07373
27 changed files with 2002 additions and 0 deletions
7
BatteryLifeLog/.classpath
Normal file
7
BatteryLifeLog/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="gen"/>
|
||||||
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
33
BatteryLifeLog/.project
Normal file
33
BatteryLifeLog/.project
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>BatteryLifeLog</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
34
BatteryLifeLog/AndroidManifest.xml
Normal file
34
BatteryLifeLog/AndroidManifest.xml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.anvisics.battery"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0">
|
||||||
|
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.BATTERY_STATS"></uses-permission>
|
||||||
|
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
||||||
|
<activity android:name=".BatteryViewActivity"
|
||||||
|
android:label="@string/app_name">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<service android:permission="android.permission.BATTERY_STATS" android:process="@string/batter_name_service" android:label="@string/batter_name_service" android:name=".BatteryLogService">
|
||||||
|
<intent-filter><action android:name="com.anvisics.BatteryLogService"></action>
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
<receiver android:name=".BatteryStatusReceiver">
|
||||||
|
<intent-filter><action android:name="android.intent.action.BATTERY_CHANGED"></action>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.WRITE_OWNER_DATA"></uses-permission>
|
||||||
|
<uses-permission android:name="android.permission.READ_OWNER_DATA"></uses-permission>
|
||||||
|
</manifest>
|
13
BatteryLifeLog/default.properties
Normal file
13
BatteryLifeLog/default.properties
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system use,
|
||||||
|
# "build.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
|
||||||
|
# Indicates whether an apk should be generated for each density.
|
||||||
|
split.density=false
|
||||||
|
# Project target.
|
||||||
|
target=android-3
|
42
BatteryLifeLog/gen/com/anvisics/battery/R.java
Normal file
42
BatteryLifeLog/gen/com/anvisics/battery/R.java
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* AUTO-GENERATED FILE. DO NOT MODIFY.
|
||||||
|
*
|
||||||
|
* This class was automatically generated by the
|
||||||
|
* aapt tool from the resource data it found. It
|
||||||
|
* should not be modified by hand.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.anvisics.battery;
|
||||||
|
|
||||||
|
public final class R {
|
||||||
|
public static final class attr {
|
||||||
|
}
|
||||||
|
public static final class color {
|
||||||
|
public static final int background=0x7f050000;
|
||||||
|
}
|
||||||
|
public static final class drawable {
|
||||||
|
public static final int icon=0x7f020000;
|
||||||
|
}
|
||||||
|
public static final class id {
|
||||||
|
public static final int Button01=0x7f070001;
|
||||||
|
public static final int Button02=0x7f070002;
|
||||||
|
public static final int Clear=0x7f070005;
|
||||||
|
public static final int Exit=0x7f070004;
|
||||||
|
public static final int Export=0x7f070006;
|
||||||
|
public static final int GridView01=0x7f070003;
|
||||||
|
public static final int LinearLayout01=0x7f070000;
|
||||||
|
}
|
||||||
|
public static final class layout {
|
||||||
|
public static final int main=0x7f030000;
|
||||||
|
public static final int mytext=0x7f030001;
|
||||||
|
}
|
||||||
|
public static final class menu {
|
||||||
|
public static final int main_menu=0x7f060000;
|
||||||
|
}
|
||||||
|
public static final class string {
|
||||||
|
public static final int app_name=0x7f040001;
|
||||||
|
public static final int batter_name_service=0x7f040004;
|
||||||
|
public static final int hello=0x7f040000;
|
||||||
|
public static final int start_service=0x7f040002;
|
||||||
|
public static final int stop_service=0x7f040003;
|
||||||
|
}
|
||||||
|
}
|
BIN
BatteryLifeLog/res/drawable/icon.png
Normal file
BIN
BatteryLifeLog/res/drawable/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
24
BatteryLifeLog/res/layout/main.xml
Normal file
24
BatteryLifeLog/res/layout/main.xml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
>
|
||||||
|
|
||||||
|
<LinearLayout android:orientation="horizontal" android:id="@+id/LinearLayout01" android:layout_width="wrap_content" android:layout_height="wrap_content">
|
||||||
|
<Button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/start_service">
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button android:id="@+id/Button02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/stop_service"></Button>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<GridView android:id="@+id/GridView01" android:layout_width="wrap_content" android:layout_height="fill_parent" android:smoothScrollbar="true" android:numColumns="auto_fit" android:focusable="false">
|
||||||
|
|
||||||
|
</GridView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
6
BatteryLifeLog/res/layout/mytext.xml
Normal file
6
BatteryLifeLog/res/layout/mytext.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
</TextView>
|
8
BatteryLifeLog/res/menu/main_menu.xml
Normal file
8
BatteryLifeLog/res/menu/main_menu.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@+id/Exit" android:title="Exit" android:orderInCategory="2"></item>
|
||||||
|
<item android:menuCategory="container" android:title="Clear All" android:alphabeticShortcut="A" android:id="@+id/Clear" android:orderInCategory="1"></item>
|
||||||
|
|
||||||
|
<item android:id="@+id/Export" android:title="Export To File"></item>
|
||||||
|
</menu>
|
9
BatteryLifeLog/res/values/strings.xml
Normal file
9
BatteryLifeLog/res/values/strings.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="hello">Hello World, BatteryViewActivity!</string>
|
||||||
|
<string name="app_name">BatteryLifeLog</string>
|
||||||
|
<string name="start_service">Запустить сервис</string>
|
||||||
|
<string name="stop_service">Остановить сервис</string>
|
||||||
|
<color name="background">#FFFFFF</color>
|
||||||
|
<string name="batter_name_service">Batter Log service</string>
|
||||||
|
</resources>
|
158
BatteryLifeLog/src/com/anvisics/battery/BatteryLogService.java
Normal file
158
BatteryLifeLog/src/com/anvisics/battery/BatteryLogService.java
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
package com.anvisics.battery;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.os.BatteryManager;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.text.format.DateFormat;
|
||||||
|
|
||||||
|
public class BatteryLogService extends Service {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return binder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private BatteryLogBinder binder = new BatteryLogBinder();
|
||||||
|
private BatteryStatusReceiver batteryStatusReceiver;
|
||||||
|
|
||||||
|
|
||||||
|
public static class BatteryLogEntry {
|
||||||
|
private int batteryLevel;
|
||||||
|
private int batteryVoltage;
|
||||||
|
private long time;
|
||||||
|
private int plugged;
|
||||||
|
private int status;
|
||||||
|
|
||||||
|
|
||||||
|
public BatteryLogEntry(){
|
||||||
|
time = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPlugged() {
|
||||||
|
return plugged;
|
||||||
|
}
|
||||||
|
public void setPlugged(int plugged) {
|
||||||
|
this.plugged = plugged;
|
||||||
|
}
|
||||||
|
public int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
public void setStatus(int status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
public int getBatteryLevel() {
|
||||||
|
return batteryLevel;
|
||||||
|
}
|
||||||
|
public void setBatteryLevel(int batteryLevel) {
|
||||||
|
this.batteryLevel = batteryLevel;
|
||||||
|
}
|
||||||
|
public int getBatteryVoltage() {
|
||||||
|
return batteryVoltage;
|
||||||
|
}
|
||||||
|
public void setBatteryVoltage(int batteryVoltage) {
|
||||||
|
this.batteryVoltage = batteryVoltage;
|
||||||
|
}
|
||||||
|
public long getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sameMeasurements(BatteryLogEntry e ){
|
||||||
|
return batteryLevel == e.batteryLevel &&
|
||||||
|
batteryVoltage == e.batteryVoltage &&
|
||||||
|
status == e.status &&
|
||||||
|
plugged == e.plugged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage(){
|
||||||
|
String statusS = "";
|
||||||
|
switch(status){
|
||||||
|
case BatteryManager.BATTERY_STATUS_CHARGING : statusS = "CHARGING";
|
||||||
|
case BatteryManager.BATTERY_STATUS_DISCHARGING: statusS = "DISCHARGING";
|
||||||
|
case BatteryManager.BATTERY_STATUS_FULL: statusS = "FULL";
|
||||||
|
case BatteryManager.BATTERY_STATUS_NOT_CHARGING: statusS = "NOT_CHARGING";
|
||||||
|
}
|
||||||
|
String pluggedS = "";
|
||||||
|
switch(plugged){
|
||||||
|
case BatteryManager.BATTERY_PLUGGED_AC: pluggedS = "PLUGGED_AC";
|
||||||
|
case BatteryManager.BATTERY_PLUGGED_USB: pluggedS = "PLUGGED_USB";
|
||||||
|
}
|
||||||
|
CharSequence timeS = DateFormat.format("MM/dd/yy k:mm",this.time);
|
||||||
|
return MessageFormat.format("{0} : battery ({1}), voltage ({2}), plugged ({3}), status ({4})",
|
||||||
|
timeS, batteryLevel, batteryVoltage, pluggedS, statusS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BatteryLogBinder extends Binder {
|
||||||
|
|
||||||
|
private List<BatteryLogEntry> entries = new ArrayList<BatteryLogEntry>();
|
||||||
|
|
||||||
|
|
||||||
|
public boolean addEntry(BatteryLogEntry e){
|
||||||
|
if(entries.isEmpty()){
|
||||||
|
entries.add(e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
BatteryLogEntry last = entries.get(entries.size() - 1);
|
||||||
|
if(!last.sameMeasurements(e) || e.getTime() - last.getTime() > 60000){
|
||||||
|
entries.add(e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void clearEntries(){
|
||||||
|
entries.clear();
|
||||||
|
}
|
||||||
|
public List<BatteryLogEntry> getEntries() {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
|
||||||
|
batteryStatusReceiver = new BatteryStatusReceiver(this);
|
||||||
|
registerReceiver(batteryStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||||
|
|
||||||
|
receiveMessage(100, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void receiveMessage(int voltage, int level, int plugged, int status){
|
||||||
|
BatteryLogEntry entry = new BatteryLogEntry();
|
||||||
|
entry.setBatteryVoltage(voltage);
|
||||||
|
entry.setBatteryLevel(level);
|
||||||
|
entry.setPlugged(plugged);
|
||||||
|
entry.setStatus(status);
|
||||||
|
binder.addEntry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLowMemory() {
|
||||||
|
super.onLowMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
unregisterReceiver(batteryStatusReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.anvisics.battery;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
public class BatteryStatusReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
private final BatteryLogService service;
|
||||||
|
|
||||||
|
public BatteryStatusReceiver(BatteryLogService service){
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
service.receiveMessage(intent.getIntExtra("voltage", -1), intent.getIntExtra("level", -1),
|
||||||
|
intent.getIntExtra("plugged", -1), intent.getIntExtra("status", -1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
177
BatteryLifeLog/src/com/anvisics/battery/BatteryViewActivity.java
Normal file
177
BatteryLifeLog/src/com/anvisics/battery/BatteryViewActivity.java
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
package com.anvisics.battery;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.GridView;
|
||||||
|
|
||||||
|
import com.anvisics.battery.BatteryLogService.BatteryLogBinder;
|
||||||
|
import com.anvisics.battery.BatteryLogService.BatteryLogEntry;
|
||||||
|
|
||||||
|
public class BatteryViewActivity extends Activity {
|
||||||
|
private Button startServiceButton;
|
||||||
|
private Button stopServiceButton;
|
||||||
|
private GridView gridView;
|
||||||
|
|
||||||
|
|
||||||
|
private final Intent serviceIntent = new Intent("com.anvisics.BatteryLogService");
|
||||||
|
|
||||||
|
ServiceConnection serviceConnection = null;
|
||||||
|
private ArrayAdapter<BatteryLogEntry> gridViewAdapter;
|
||||||
|
private BatteryLogBinder binder = null;
|
||||||
|
|
||||||
|
private class MyServiceConnection implements ServiceConnection {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
if(service instanceof BatteryLogBinder){
|
||||||
|
gridViewAdapter.clear();
|
||||||
|
binder = (BatteryLogBinder) service;
|
||||||
|
List<BatteryLogEntry> entries = ((BatteryLogBinder) service).getEntries();
|
||||||
|
for(int i = entries.size() - 1; i>=0; i--){
|
||||||
|
gridViewAdapter.add(entries.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
gridViewAdapter.clear();
|
||||||
|
binder = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.main);
|
||||||
|
|
||||||
|
|
||||||
|
startServiceButton = (Button)findViewById(R.id.Button01);
|
||||||
|
stopServiceButton = (Button)findViewById(R.id.Button02);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
gridView = (GridView) findViewById(R.id.GridView01);
|
||||||
|
|
||||||
|
gridView.setNumColumns(1);
|
||||||
|
gridView.setVerticalSpacing(3);
|
||||||
|
gridViewAdapter = new ArrayAdapter<BatteryLogEntry>(getWindow().getContext(), R.layout.mytext);
|
||||||
|
gridView.setAdapter(gridViewAdapter);
|
||||||
|
|
||||||
|
|
||||||
|
startServiceButton.setOnClickListener(new OnClickListener(){
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
ComponentName name = getWindow().getContext().startService(serviceIntent);
|
||||||
|
if(name != null){
|
||||||
|
stopServiceButton.setEnabled(true);
|
||||||
|
startServiceButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stopServiceButton.setOnClickListener(new OnClickListener(){
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
boolean stopService = getWindow().getContext().stopService(serviceIntent);
|
||||||
|
if(stopService){
|
||||||
|
stopServiceButton.setEnabled(false);
|
||||||
|
startServiceButton.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ComponentName componentName = getWindow().getContext().startService(serviceIntent);
|
||||||
|
startServiceButton.setEnabled(componentName == null);
|
||||||
|
stopServiceButton.setEnabled(componentName != null);
|
||||||
|
serviceConnection = new MyServiceConnection();
|
||||||
|
|
||||||
|
|
||||||
|
getWindow().getContext().bindService(serviceIntent, serviceConnection, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.main_menu, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
if(item.getItemId() == R.id.Clear){
|
||||||
|
if(binder != null){
|
||||||
|
binder.clearEntries();
|
||||||
|
gridViewAdapter.clear();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (item.getItemId() == R.id.Export) {
|
||||||
|
if (binder == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
File directory = Environment.getExternalStorageDirectory();
|
||||||
|
if (directory.canWrite()) {
|
||||||
|
File f = new File(directory, "BatteryLog.txt");
|
||||||
|
int i = 1;
|
||||||
|
while (f.exists()) {
|
||||||
|
f = new File(directory, "BatteryLog" + (++i) + ".txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedWriter writer = new BufferedWriter(
|
||||||
|
new FileWriter(f));
|
||||||
|
List<BatteryLogEntry> entries = binder.getEntries();
|
||||||
|
for (i = entries.size() - 1; i >= 0; i--) {
|
||||||
|
writer.write(entries.get(i).toString());
|
||||||
|
}
|
||||||
|
writer.close();
|
||||||
|
binder.clearEntries();
|
||||||
|
gridViewAdapter.clear();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("batteryLog", "Can't export file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(item.getItemId() == R.id.Exit){
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if(serviceConnection != null){
|
||||||
|
getWindow().getContext().unbindService(serviceConnection);
|
||||||
|
serviceConnection = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
9
DataExtractionOSM/.classpath
Normal file
9
DataExtractionOSM/.classpath
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="lib" path="lib/bzip2-20090327.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-logging-1.1.1.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/osmosis-0.32.jar"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
17
DataExtractionOSM/.project
Normal file
17
DataExtractionOSM/.project
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>DataExtractionOSM</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
BIN
DataExtractionOSM/lib/bzip2-20090327.jar
Normal file
BIN
DataExtractionOSM/lib/bzip2-20090327.jar
Normal file
Binary file not shown.
BIN
DataExtractionOSM/lib/commons-logging-1.1.1.jar
Normal file
BIN
DataExtractionOSM/lib/commons-logging-1.1.1.jar
Normal file
Binary file not shown.
BIN
DataExtractionOSM/lib/jpf.jar
Normal file
BIN
DataExtractionOSM/lib/jpf.jar
Normal file
Binary file not shown.
BIN
DataExtractionOSM/lib/osmosis-0.32.jar
Normal file
BIN
DataExtractionOSM/lib/osmosis-0.32.jar
Normal file
Binary file not shown.
10
DataExtractionOSM/src/com/anvisics/Constants.java
Normal file
10
DataExtractionOSM/src/com/anvisics/Constants.java
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package com.anvisics;
|
||||||
|
|
||||||
|
public interface Constants {
|
||||||
|
|
||||||
|
// TODO externalize proper way
|
||||||
|
public String pathToTestDataDir = "E:\\Information\\gps\\OpenMap\\";
|
||||||
|
|
||||||
|
public String ADDR_HOUSE_NUMBER = "addr:housenumber";
|
||||||
|
public String ADDR_STREET = "addr:street";
|
||||||
|
}
|
528
DataExtractionOSM/src/com/anvisics/DataExtraction.java
Normal file
528
DataExtractionOSM/src/com/anvisics/DataExtraction.java
Normal file
|
@ -0,0 +1,528 @@
|
||||||
|
package com.anvisics;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import javax.swing.DefaultListCellRenderer;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JList;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JSplitPane;
|
||||||
|
import javax.swing.JTextField;
|
||||||
|
import javax.swing.JTree;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import javax.swing.event.TreeSelectionEvent;
|
||||||
|
import javax.swing.event.TreeSelectionListener;
|
||||||
|
import javax.swing.event.UndoableEditEvent;
|
||||||
|
import javax.swing.event.UndoableEditListener;
|
||||||
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.parsers.SAXParser;
|
||||||
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
|
import javax.xml.stream.XMLStreamException;
|
||||||
|
|
||||||
|
import org.apache.tools.bzip2.CBZip2InputStream;
|
||||||
|
import org.openstreetmap.osmosis.core.container.v0_6.EntityContainer;
|
||||||
|
import org.openstreetmap.osmosis.core.container.v0_6.NodeContainer;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Entity;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Tag;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Way;
|
||||||
|
import org.openstreetmap.osmosis.core.task.v0_6.Sink;
|
||||||
|
import org.openstreetmap.osmosis.core.xml.v0_6.impl.OsmHandler;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import com.anvisics.MapPanel.IMapLocationListener;
|
||||||
|
import com.anvisics.NodeUtil.LatLon;
|
||||||
|
import com.anvisics.data.City;
|
||||||
|
import com.anvisics.data.Region;
|
||||||
|
import com.anvisics.data.Street;
|
||||||
|
import com.anvisics.data.City.CityType;
|
||||||
|
|
||||||
|
|
||||||
|
// TO implement
|
||||||
|
// 1. Full structured search for town/street/building.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing#Is_inside.2Foutside
|
||||||
|
* http://wiki.openstreetmap.org/wiki/Relations/Proposed/Postal_Addresses
|
||||||
|
* http://wiki.openstreetmap.org/wiki/Proposed_features/House_numbers/Karlsruhe_Schema#Tags (node, way)
|
||||||
|
*
|
||||||
|
* 1. node - place : country, state, region, county, city, town, village, hamlet, suburb
|
||||||
|
* That node means label for place ! It is widely used in OSM.
|
||||||
|
*
|
||||||
|
* 2. way - highway : primary, secondary, service.
|
||||||
|
* That node means label for street if it is in city (primary, secondary, residential, tertiary, living_street),
|
||||||
|
* beware sometimes that roads could outside city. Usage : often
|
||||||
|
*
|
||||||
|
* outside city : trunk, motorway, motorway_link...
|
||||||
|
* special tags : lanes - 3, maxspeed - 90, bridge
|
||||||
|
*
|
||||||
|
* 3. relation - type = address. address:type : country, a1, a2, a3, a4, a5, a6, ... hno.
|
||||||
|
* member:node role=label :
|
||||||
|
* member:relation role=border :
|
||||||
|
* member:node role=a1,a2... :
|
||||||
|
*
|
||||||
|
* 4. node, way - addr:housenumber(+), addr:street(+), addr:country(+/-), addr:city(-)
|
||||||
|
* building=yes
|
||||||
|
*
|
||||||
|
* 5. relation - boundary=administrative, admin_level : 1, 2, ....
|
||||||
|
*
|
||||||
|
* 6. node, way - addr:postcode =?
|
||||||
|
* relation - type=postal_code (members way, node), postal_code=?
|
||||||
|
*
|
||||||
|
* 7. node, way - amenity=?
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DataExtraction implements IMapLocationListener {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XMLStreamException {
|
||||||
|
new DataExtraction().testReadingOsmFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static boolean parseMinsk = true;
|
||||||
|
private static boolean parseOSM = true;
|
||||||
|
|
||||||
|
///////////////////////////////////////////
|
||||||
|
// 1. Reading data - preparing data for UI
|
||||||
|
public void testReadingOsmFile() throws ParserConfigurationException, SAXException, IOException, XMLStreamException {
|
||||||
|
|
||||||
|
InputStream stream ;
|
||||||
|
if(parseMinsk){
|
||||||
|
stream = new FileInputStream(Constants.pathToTestDataDir+"minsk_old.osm");
|
||||||
|
} else {
|
||||||
|
// stream = new FileInputStream(Constants.pathToTestDataDir+"belarus_2010_04_01.osm.bz2");
|
||||||
|
// stream = new FileInputStream(Constants.pathToTestDataDir+"minsk_old.osm");
|
||||||
|
stream = new FileInputStream(Constants.pathToTestDataDir+"minsk_2010_04_26.osm.bz2");
|
||||||
|
if (stream.read() != 66 || stream.read() != 90)
|
||||||
|
throw new RuntimeException(
|
||||||
|
"The source stream must start with the characters BZ if it is to be read as a BZip2 stream.");
|
||||||
|
else
|
||||||
|
stream = new CBZip2InputStream(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
System.out.println("USED Memory " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1e6);
|
||||||
|
long st = System.currentTimeMillis();
|
||||||
|
|
||||||
|
|
||||||
|
// preloaded data
|
||||||
|
final List<Node> places = new ArrayList<Node>();
|
||||||
|
final Map<Long, LatLon> nodes = new HashMap<Long, LatLon>();
|
||||||
|
final List<Entity> buildings = new ArrayList<Entity>();
|
||||||
|
final List<Node> amenities = new ArrayList<Node>();
|
||||||
|
|
||||||
|
|
||||||
|
// highways count
|
||||||
|
final Map<String, Integer> mapWays = new LinkedHashMap<String, Integer>();
|
||||||
|
|
||||||
|
if (parseOSM) {
|
||||||
|
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||||
|
parser.parse(stream, new OsmHandler(new Sink() {
|
||||||
|
@Override
|
||||||
|
public void process(EntityContainer entityContainer) {
|
||||||
|
if (entityContainer instanceof NodeContainer) {
|
||||||
|
NodeContainer rc = (NodeContainer) entityContainer;
|
||||||
|
if (NodeUtil.getTag(rc.getEntity(), "place") != null) {
|
||||||
|
places.add(rc.getEntity());
|
||||||
|
if (places.size() % 500 == 0) {
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
System.out.print("-");
|
||||||
|
}
|
||||||
|
nodes.put(rc.getEntity().getId(), new LatLon(rc.getEntity().getLatitude(),
|
||||||
|
rc.getEntity().getLongitude()));
|
||||||
|
if (NodeUtil.getTag(entityContainer.getEntity(), "amenity") != null) {
|
||||||
|
amenities.add((Node) entityContainer.getEntity());
|
||||||
|
} else if (NodeUtil.getTag(entityContainer.getEntity(), "shop") != null) {
|
||||||
|
Entity n = entityContainer.getEntity();
|
||||||
|
n.getTags().add(new Tag("amenity", "shop"));
|
||||||
|
amenities.add((Node) n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (NodeUtil.tag(entityContainer.getEntity(), "building", "yes")) {
|
||||||
|
Entity e = entityContainer.getEntity();
|
||||||
|
if (NodeUtil.getTag(e, Constants.ADDR_HOUSE_NUMBER) != null
|
||||||
|
&& NodeUtil.getTag(e, Constants.ADDR_STREET) != null) {
|
||||||
|
buildings.add(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NodeUtil.getTag(entityContainer.getEntity(), "highway") != null) {
|
||||||
|
String h = NodeUtil.getTag(entityContainer.getEntity(), "highway");
|
||||||
|
if(!mapWays.containsKey(h)){
|
||||||
|
mapWays.put(h, 0);
|
||||||
|
}
|
||||||
|
mapWays.put(h, mapWays.get(h) + 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void complete() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
}
|
||||||
|
}, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("\n"+mapWays);
|
||||||
|
System.out.println(System.currentTimeMillis() - st);
|
||||||
|
|
||||||
|
// 1. found towns !
|
||||||
|
Region country = new Region(null);
|
||||||
|
for (Node s : places) {
|
||||||
|
String place = NodeUtil.getTag(s, "place");
|
||||||
|
if(place == null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if("country".equals(place)){
|
||||||
|
country.setEntity(s);
|
||||||
|
} else {
|
||||||
|
City registerCity = country.registerCity(s);
|
||||||
|
if(registerCity == null){
|
||||||
|
System.out.println(place + " - " + NodeUtil.getTag(s, "name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. found buildings (index addresses)
|
||||||
|
for(Entity b : buildings){
|
||||||
|
LatLon center ;
|
||||||
|
if(b instanceof Node){
|
||||||
|
center = NodeUtil.getLatLon((Node) b);
|
||||||
|
} else {
|
||||||
|
center = NodeUtil.getWeightCenter((Way) b, nodes);
|
||||||
|
}
|
||||||
|
// TODO first of all tag could be checked NodeUtil.getTag(e, "addr:city")
|
||||||
|
City city = country.getClosestCity(center);
|
||||||
|
if(city != null){
|
||||||
|
city.registerBuilding(center, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Node node : amenities){
|
||||||
|
country.registerAmenity(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
runUI(country);
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("USED Memory " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1e6);
|
||||||
|
System.out.println("TIME : " + (System.currentTimeMillis() - st));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////
|
||||||
|
// 2. Showing UI
|
||||||
|
|
||||||
|
protected City selectedCity;
|
||||||
|
|
||||||
|
private MapPanel mapPanel = new MapPanel(new File(Constants.pathToTestDataDir+"MinskTiles"));
|
||||||
|
|
||||||
|
private DefaultMutableTreeNode amenitiesTree;
|
||||||
|
private JTree treePlaces;
|
||||||
|
|
||||||
|
public void runUI(final Region r){
|
||||||
|
JFrame frame = new JFrame("Tree of choose");
|
||||||
|
try {
|
||||||
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
DefaultMutableTreeNode root = new DataExtractionTreeNode(r.getName(), r);
|
||||||
|
amenitiesTree = new DataExtractionTreeNode("Amenities", r);
|
||||||
|
amenitiesTree.add(new DataExtractionTreeNode("closest", r));
|
||||||
|
root.add(amenitiesTree);
|
||||||
|
for(CityType t : CityType.values()){
|
||||||
|
DefaultMutableTreeNode cityTree = new DataExtractionTreeNode(t.toString(), t);
|
||||||
|
root.add(cityTree);
|
||||||
|
for(City ct : r.getCitiesByType(t)){
|
||||||
|
DefaultMutableTreeNode cityNodeTree = new DataExtractionTreeNode(ct.getName(), ct);
|
||||||
|
cityTree.add(cityNodeTree);
|
||||||
|
|
||||||
|
for(Street str : ct.getStreets()){
|
||||||
|
DefaultMutableTreeNode strTree = new DataExtractionTreeNode(str.getName(), str);
|
||||||
|
cityNodeTree.add(strTree);
|
||||||
|
for(Entity e : str.getBuildings()){
|
||||||
|
DefaultMutableTreeNode building = new DataExtractionTreeNode(NodeUtil.getTag(e, Constants.ADDR_HOUSE_NUMBER), e);
|
||||||
|
strTree.add(building);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
frame.addWindowListener(new ExitListener());
|
||||||
|
Container content = frame.getContentPane();
|
||||||
|
frame.setFocusable(true);
|
||||||
|
|
||||||
|
|
||||||
|
treePlaces = new JTree(root);
|
||||||
|
final JList jList = new JList();
|
||||||
|
jList.setCellRenderer(new DefaultListCellRenderer(){
|
||||||
|
private static final long serialVersionUID = 4661949460526837891L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(JList list,
|
||||||
|
Object value, int index, boolean isSelected,
|
||||||
|
boolean cellHasFocus) {
|
||||||
|
super.getListCellRendererComponent(list, value, index, isSelected,
|
||||||
|
cellHasFocus);
|
||||||
|
if(value instanceof City){
|
||||||
|
setText(((City)value).getName());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JSplitPane panelForTreeAndImage = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(treePlaces), mapPanel);
|
||||||
|
panelForTreeAndImage.setResizeWeight(0.2);
|
||||||
|
mapPanel.setFocusable(true);
|
||||||
|
mapPanel.addMapLocationListener(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(jList), panelForTreeAndImage);
|
||||||
|
pane.setResizeWeight(0.2);
|
||||||
|
content.add(pane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
final JLabel label = new JLabel();
|
||||||
|
content.add(label, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
|
final JTextField textField = new JTextField();
|
||||||
|
final JButton button = new JButton();
|
||||||
|
button.setText("Set town");
|
||||||
|
panel.add(textField, BorderLayout.CENTER);
|
||||||
|
panel.add(button, BorderLayout.EAST);
|
||||||
|
|
||||||
|
content.add(panel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
|
||||||
|
updateListCities(r, textField.getText(), jList);
|
||||||
|
textField.getDocument().addUndoableEditListener(new UndoableEditListener(){
|
||||||
|
@Override
|
||||||
|
public void undoableEditHappened(UndoableEditEvent e) {
|
||||||
|
updateListCities(r, textField.getText(), jList);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
button.addActionListener(new ActionListener(){
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
selectedCity = (City)jList.getSelectedValue();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
jList.addListSelectionListener(new ListSelectionListener(){
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
if(jList.getSelectedValue() != null){
|
||||||
|
Node node = ((City)jList.getSelectedValue()).getNode();
|
||||||
|
String text = "Lat : " + node.getLatitude() + " Lon " + node.getLongitude();
|
||||||
|
if(selectedCity != null){
|
||||||
|
text += " distance " + NodeUtil.getDistance(selectedCity.getNode(), node);
|
||||||
|
}
|
||||||
|
label.setText(text);
|
||||||
|
mapPanel.setLatLon(node.getLatitude(), node.getLongitude());
|
||||||
|
} else {
|
||||||
|
String text = selectedCity == null ? "" : selectedCity.getName();
|
||||||
|
label.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
treePlaces.addTreeSelectionListener(new TreeSelectionListener(){
|
||||||
|
@Override
|
||||||
|
public void valueChanged(TreeSelectionEvent e) {
|
||||||
|
if (e.getPath() != null) {
|
||||||
|
if (e.getPath().getLastPathComponent() instanceof DefaultMutableTreeNode) {
|
||||||
|
Object o = ((DefaultMutableTreeNode) e.getPath().getLastPathComponent()).getUserObject();
|
||||||
|
|
||||||
|
if (o instanceof City) {
|
||||||
|
City c = (City) o;
|
||||||
|
mapPanel.setLatLon(c.getNode().getLatitude(), c.getNode().getLongitude());
|
||||||
|
mapPanel.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o instanceof Entity) {
|
||||||
|
Entity c = (Entity) o;
|
||||||
|
if (c instanceof Node) {
|
||||||
|
mapPanel.setLatLon(((Node) c).getLatitude(), ((Node) c).getLongitude());
|
||||||
|
// mapPanel.requestFocus();
|
||||||
|
} else {
|
||||||
|
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.getPath().getPathComponent(
|
||||||
|
e.getPath().getPathCount() - 2);
|
||||||
|
if (n.getUserObject() instanceof Street) {
|
||||||
|
Street str = (Street) n.getUserObject();
|
||||||
|
LatLon l = str.getLocationBuilding(c);
|
||||||
|
mapPanel.setLatLon(l.getLatitude(), l.getLongitude());
|
||||||
|
mapPanel.requestFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
frame.setSize(1024, 768);
|
||||||
|
frame.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void locationChanged(final double newLatitude, final double newLongitude){
|
||||||
|
Region reg = (Region) amenitiesTree.getUserObject();
|
||||||
|
List<Node> closestAmenities = reg.getClosestAmenities(newLatitude, newLongitude);
|
||||||
|
Collections.sort(closestAmenities, new Comparator<Node>(){
|
||||||
|
@Override
|
||||||
|
public int compare(Node o1, Node o2) {
|
||||||
|
return Double.compare(NodeUtil.getDistance(o1, newLatitude, newLongitude),
|
||||||
|
NodeUtil.getDistance(o2, newLatitude, newLongitude));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, List<Node>> filter = new TreeMap<String, List<Node>>();
|
||||||
|
for(Node n : closestAmenities){
|
||||||
|
String type = NodeUtil.getTag(n, "amenity");
|
||||||
|
if(!filter.containsKey(type)){
|
||||||
|
filter.put(type, new ArrayList<Node>());
|
||||||
|
}
|
||||||
|
filter.get(type).add(n);
|
||||||
|
}
|
||||||
|
for(int i=1; i< amenitiesTree.getChildCount(); ){
|
||||||
|
if(!filter.containsKey(((DefaultMutableTreeNode)amenitiesTree.getChildAt(i)).getUserObject())){
|
||||||
|
amenitiesTree.remove(i);
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
((DefaultMutableTreeNode)amenitiesTree.getChildAt(0)).removeAllChildren();
|
||||||
|
|
||||||
|
|
||||||
|
for(int i=0; i<15 && i < closestAmenities.size(); i++){
|
||||||
|
Node n = closestAmenities.get(i);
|
||||||
|
String type = NodeUtil.getTag(n, "amenity");
|
||||||
|
String name = NodeUtil.getTag(n, "name");
|
||||||
|
int dist = (int) (NodeUtil.getDistance(n, newLatitude, newLongitude));
|
||||||
|
String str = type +" "+(name == null ? n.getId() : name) +" [" +dist+" m ]";
|
||||||
|
((DefaultMutableTreeNode)amenitiesTree.getChildAt(0)).add(
|
||||||
|
new DataExtractionTreeNode(str, n));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String s : filter.keySet()){
|
||||||
|
DefaultMutableTreeNode p = null;
|
||||||
|
for(int i=0; i< amenitiesTree.getChildCount(); i++){
|
||||||
|
if(s.equals(((DefaultMutableTreeNode)amenitiesTree.getChildAt(i)).getUserObject())){
|
||||||
|
p = ((DefaultMutableTreeNode)amenitiesTree.getChildAt(i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p == null) {
|
||||||
|
p = new DefaultMutableTreeNode(s);
|
||||||
|
}
|
||||||
|
// Map<Node, DataExtractionTreeNode> consists = new LinkedHashMap<Node, DataExtractionTreeNode>();
|
||||||
|
// for(Node n : filter.get(s)){
|
||||||
|
// consists.put(n, null);
|
||||||
|
// }
|
||||||
|
// for(int i=0; i<p.getChildCount();){
|
||||||
|
// Object userObject = ((DefaultMutableTreeNode)p.getChildAt(i)).getUserObject();
|
||||||
|
// if(consists.containsKey(userObject)){
|
||||||
|
// consists.put((Node) userObject, (DataExtractionTreeNode) p.getChildAt(i));
|
||||||
|
// i++;
|
||||||
|
// } else {
|
||||||
|
// p.remove(i);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
p.removeAllChildren();
|
||||||
|
for(Node n : filter.get(s)){
|
||||||
|
String name = NodeUtil.getTag(n, "name");
|
||||||
|
int dist = (int) (NodeUtil.getDistance(n, newLatitude, newLongitude));
|
||||||
|
String str = (name == null ? n.getId() : name) +" [" +dist+" m ]";
|
||||||
|
// if(consists.get(n) != null){
|
||||||
|
// consists.get(n).setName(str);
|
||||||
|
// } else {
|
||||||
|
DataExtractionTreeNode node = new DataExtractionTreeNode(str, n);
|
||||||
|
p.add(node);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
amenitiesTree.add(p);
|
||||||
|
}
|
||||||
|
treePlaces.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateListCities(Region r, String text, JList jList){
|
||||||
|
Collection<City> city = r.getSuggestedCities(text, 100);
|
||||||
|
City[] names = new City[city.size()];
|
||||||
|
int i=0;
|
||||||
|
for(City c : city){
|
||||||
|
names[i++] = c;
|
||||||
|
}
|
||||||
|
jList.setListData(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class DataExtractionTreeNode extends DefaultMutableTreeNode {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public DataExtractionTreeNode(String name, Object userObject){
|
||||||
|
super(userObject);
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public static class ExitListener extends WindowAdapter {
|
||||||
|
public void windowClosing(WindowEvent event) {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
335
DataExtractionOSM/src/com/anvisics/MapPanel.java
Normal file
335
DataExtractionOSM/src/com/anvisics/MapPanel.java
Normal file
|
@ -0,0 +1,335 @@
|
||||||
|
package com.anvisics;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
|
import com.anvisics.DataExtraction.ExitListener;
|
||||||
|
|
||||||
|
public class MapPanel extends JPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public interface IMapLocationListener {
|
||||||
|
void locationChanged(double newLatitude, double newLongitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
JFrame frame = new JFrame("Tree of choose");
|
||||||
|
try {
|
||||||
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
frame.addWindowListener(new ExitListener());
|
||||||
|
Container content = frame.getContentPane();
|
||||||
|
|
||||||
|
// MapPanel panel = new MapPanel(new ZipFile(Constants.pathToTestDataDir + "MinskTiles.zipp"));
|
||||||
|
MapPanel panel = new MapPanel(new File(Constants.pathToTestDataDir + "MinskTiles"));
|
||||||
|
|
||||||
|
content.add(panel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
frame.setSize(512, 512);
|
||||||
|
frame.setVisible(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int tileSize = 256;
|
||||||
|
private BufferedImage[][] images;
|
||||||
|
private int xStartingImage = 0;
|
||||||
|
private int yStartingImage = 0;
|
||||||
|
|
||||||
|
private final File fileWithTiles;
|
||||||
|
private int zoom = 15;
|
||||||
|
|
||||||
|
// degree measurements (-180, 180)
|
||||||
|
// äîëãîòà
|
||||||
|
private double longitude = 27.56;
|
||||||
|
// øèðîòà
|
||||||
|
// degree measurements (90, -90)
|
||||||
|
private double latitude = 53.9;
|
||||||
|
|
||||||
|
private List<IMapLocationListener> listeners = new ArrayList<IMapLocationListener>();
|
||||||
|
|
||||||
|
private String map = "Mapnik";
|
||||||
|
|
||||||
|
public MapPanel(File fileWithTiles) {
|
||||||
|
this.fileWithTiles = fileWithTiles;
|
||||||
|
initUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public double getXTile(){
|
||||||
|
return NodeUtil.getTileNumberX(zoom, longitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getYTile(){
|
||||||
|
return NodeUtil.getTileNumberY(zoom, latitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
System.out.println("draw");
|
||||||
|
if (images != null) {
|
||||||
|
for (int i = 0; i < images.length; i++) {
|
||||||
|
for (int j = 0; j < images[i].length; j++) {
|
||||||
|
if(images[i][j] == null){
|
||||||
|
if((i+j + (int)getXTile() + (int)getYTile()) % 2 == 0){
|
||||||
|
g.setColor(Color.gray);
|
||||||
|
} else {
|
||||||
|
g.setColor(Color.white);
|
||||||
|
}
|
||||||
|
g.fillRect(i * tileSize+xStartingImage, j * tileSize + yStartingImage, tileSize, tileSize);
|
||||||
|
} else {
|
||||||
|
g.drawImage(images[i][j], i * tileSize+xStartingImage, j * tileSize + yStartingImage, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.setColor(Color.black);
|
||||||
|
|
||||||
|
g.fillOval(getWidth()/2 - 2, getHeight()/2 -2, 4, 4);
|
||||||
|
g.drawOval(getWidth()/2 - 2, getHeight()/2 -2, 4, 4);
|
||||||
|
g.drawOval(getWidth()/2 - 5, getHeight()/2 -5, 10, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFile(int x, int y){
|
||||||
|
return map +"/"+zoom+"/"+(x) +"/"+y+".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, BufferedImage> cache = new HashMap<String, BufferedImage>();
|
||||||
|
public BufferedImage getImageFor(int x, int y) throws IOException{
|
||||||
|
String file = getFile(x, y);
|
||||||
|
if(!cache.containsKey(file)){
|
||||||
|
// ZipEntry en = fileWithTiles.getEntry(file);
|
||||||
|
File en = new File(fileWithTiles, file);
|
||||||
|
if(cache.size() > 1000){
|
||||||
|
ArrayList<String> list = new ArrayList<String>(cache.keySet());
|
||||||
|
for(int i=0; i<list.size(); i+=2){
|
||||||
|
cache.remove(list.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if(en != null){
|
||||||
|
if(en.exists()){
|
||||||
|
// cache.put(file, ImageIO.read(fileWithTiles.getInputStream(en)));
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
cache.put(file, ImageIO.read(en));
|
||||||
|
System.out.println("Loaded " + (System.currentTimeMillis() - time));
|
||||||
|
} else {
|
||||||
|
cache.put(file, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache.get(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO async loading images (show busy cursor while it is loaded)
|
||||||
|
public void prepareImage(){
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (images != null) {
|
||||||
|
for (int i = 0; i < images.length; i++) {
|
||||||
|
for (int j = 0; j < images[i].length; j++) {
|
||||||
|
// dispose
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double xTile = getXTile();
|
||||||
|
double yTile = getYTile();
|
||||||
|
double leftX = (getSize().width/2d - (xTile - Math.floor(xTile)) *tileSize)/tileSize;
|
||||||
|
double leftY = (getSize().height/2d - (yTile - Math.floor(yTile)) *tileSize)/tileSize;
|
||||||
|
|
||||||
|
int xStartInd = (int) (Math.floor(xTile) - Math.ceil(leftX));
|
||||||
|
int yStartInd = (int) (Math.floor(yTile) - Math.ceil(leftY));
|
||||||
|
|
||||||
|
xStartingImage = (int) ((leftX - Math.ceil(leftX))*tileSize);
|
||||||
|
yStartingImage = (int) ((leftY - Math.ceil(leftY))*tileSize);
|
||||||
|
|
||||||
|
int tileXCount = (int) Math.ceil((getSize().width - xStartingImage)/ (double)tileSize );
|
||||||
|
int tileYCount = (int) Math.ceil((getSize().height- yStartingImage)/ (double)tileSize );
|
||||||
|
images = new BufferedImage[tileXCount][tileYCount];
|
||||||
|
for(int i=0; i<images.length; i++){
|
||||||
|
for(int j=0; j<images[i].length; j++){
|
||||||
|
images[i][j]= getImageFor(xStartInd + i, yStartInd + j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repaint();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
setFocusable(true);
|
||||||
|
addComponentListener(new ComponentAdapter(){
|
||||||
|
public void componentResized(ComponentEvent e) {
|
||||||
|
prepareImage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MapMouseAdapter mouse = new MapMouseAdapter();
|
||||||
|
addMouseListener(mouse);
|
||||||
|
addMouseMotionListener(mouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setZoom(int zoom){
|
||||||
|
this.zoom = zoom;
|
||||||
|
prepareImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLatLon(double latitude, double longitude){
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
prepareImage();
|
||||||
|
fireMapLocationListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLatitude() {
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLongitude() {
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZoom() {
|
||||||
|
return zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMap(){
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapName(String map){
|
||||||
|
this.map = map;
|
||||||
|
prepareImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMapLocationListener(IMapLocationListener l){
|
||||||
|
listeners.add(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeMapLocationListener(IMapLocationListener l){
|
||||||
|
listeners.remove(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fireMapLocationListeners(){
|
||||||
|
for(IMapLocationListener l : listeners){
|
||||||
|
l.locationChanged(latitude, longitude);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processKeyEvent(KeyEvent e) {
|
||||||
|
boolean processed = false;
|
||||||
|
if (e.getID() == KeyEvent.KEY_RELEASED) {
|
||||||
|
|
||||||
|
if (e.getKeyCode() == 37) {
|
||||||
|
longitude = NodeUtil.getLongitudeFromTile(zoom, getXTile()-0.5);
|
||||||
|
processed = true;
|
||||||
|
} else if (e.getKeyCode() == 39) {
|
||||||
|
longitude = NodeUtil.getLongitudeFromTile(zoom, getXTile()+0.5);
|
||||||
|
processed = true;
|
||||||
|
} else if (e.getKeyCode() == 38) {
|
||||||
|
latitude = NodeUtil.getLatitudeFromTile(zoom, getYTile()-0.5);
|
||||||
|
processed = true;
|
||||||
|
} else if (e.getKeyCode() == 40) {
|
||||||
|
latitude = NodeUtil.getLatitudeFromTile(zoom, getYTile()+0.5);
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(e.getID() == KeyEvent.KEY_TYPED){
|
||||||
|
if(e.getKeyChar() == '+'){
|
||||||
|
zoom ++;
|
||||||
|
processed = true;
|
||||||
|
} else if(e.getKeyChar() == '-'){
|
||||||
|
zoom --;
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(processed){
|
||||||
|
e.consume();
|
||||||
|
prepareImage();
|
||||||
|
fireMapLocationListeners();
|
||||||
|
}
|
||||||
|
super.processKeyEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MapMouseAdapter extends MouseAdapter {
|
||||||
|
private Point startDragging = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
if(e.getButton() == MouseEvent.BUTTON1){
|
||||||
|
requestFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dragTo(Point p){
|
||||||
|
double dx = (startDragging.x - (double)p.x)/tileSize;
|
||||||
|
double dy = (startDragging.y - (double)p.y)/tileSize;
|
||||||
|
double lat = NodeUtil.getLatitudeFromTile(zoom, getYTile() + dy);
|
||||||
|
double lon = NodeUtil.getLongitudeFromTile(zoom, getXTile() + dx);
|
||||||
|
setLatLon(lat, lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDragged(MouseEvent e) {
|
||||||
|
if(startDragging != null){
|
||||||
|
if(Math.abs(e.getPoint().x - startDragging.x) + Math.abs(e.getPoint().y - startDragging.y) >= 8){
|
||||||
|
dragTo(e.getPoint());
|
||||||
|
startDragging = e.getPoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent e) {
|
||||||
|
if(e.getButton() == MouseEvent.BUTTON3){
|
||||||
|
if(startDragging == null){
|
||||||
|
startDragging = e.getPoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void mouseReleased(MouseEvent e) {
|
||||||
|
if(e.getButton() == MouseEvent.BUTTON3){
|
||||||
|
if(startDragging != null){
|
||||||
|
dragTo(e.getPoint());
|
||||||
|
fireMapLocationListeners();
|
||||||
|
startDragging = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.mouseReleased(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
213
DataExtractionOSM/src/com/anvisics/NodeUtil.java
Normal file
213
DataExtractionOSM/src/com/anvisics/NodeUtil.java
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
package com.anvisics;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Entity;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Tag;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Way;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.WayNode;
|
||||||
|
|
||||||
|
public class NodeUtil {
|
||||||
|
|
||||||
|
public static class LatLon {
|
||||||
|
private final double longitude;
|
||||||
|
private final double latitude;
|
||||||
|
|
||||||
|
public LatLon(double latitude, double longitude){
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
long temp;
|
||||||
|
temp = Double.doubleToLongBits(latitude);
|
||||||
|
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||||
|
temp = Double.doubleToLongBits(longitude);
|
||||||
|
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
LatLon other = (LatLon) obj;
|
||||||
|
if (Double.doubleToLongBits(latitude) != Double
|
||||||
|
.doubleToLongBits(other.latitude))
|
||||||
|
return false;
|
||||||
|
if (Double.doubleToLongBits(longitude) != Double
|
||||||
|
.doubleToLongBits(other.longitude))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Lat " + latitude +" Lon "+ longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLatitude() {
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLongitude() {
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getTag(Entity e, String name){
|
||||||
|
for(Tag t : e.getTags()){
|
||||||
|
if(name.equals(t.getKey())){
|
||||||
|
return t.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDistance(Node e1, Node e2){
|
||||||
|
return getDistance(e1.getLatitude(), e1.getLongitude(), e2.getLatitude(), e2.getLongitude());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDistance(Node e1, double latitude, double longitude){
|
||||||
|
return getDistance(e1.getLatitude(), e1.getLongitude(), latitude, longitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDistance(Node e1, LatLon point){
|
||||||
|
return getDistance(e1.getLatitude(), e1.getLongitude(), point.getLatitude(), point.getLongitude());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets distance in meters
|
||||||
|
*/
|
||||||
|
public static double getDistance(double lat1, double lon1, double lat2, double lon2){
|
||||||
|
double R = 6371; // km
|
||||||
|
double dLat = Math.toRadians(lat2-lat1);
|
||||||
|
double dLon = Math.toRadians(lon2-lon1);
|
||||||
|
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
||||||
|
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
|
||||||
|
Math.sin(dLon/2) * Math.sin(dLon/2);
|
||||||
|
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||||||
|
return R * c * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LatLon getWeightCenter(Collection<LatLon> nodes){
|
||||||
|
if(nodes.isEmpty()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
double longitude = 0;
|
||||||
|
double latitude = 0;
|
||||||
|
for(LatLon n : nodes){
|
||||||
|
longitude += n.getLongitude();
|
||||||
|
latitude += n.getLatitude();
|
||||||
|
}
|
||||||
|
return new LatLon(latitude/nodes.size(), longitude/nodes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LatLon getWeightCenterForNodes(Collection<Node> nodes){
|
||||||
|
if(nodes.isEmpty()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
double longitude = 0;
|
||||||
|
double latitude = 0;
|
||||||
|
for(Node n : nodes){
|
||||||
|
longitude += n.getLongitude();
|
||||||
|
latitude += n.getLatitude();
|
||||||
|
}
|
||||||
|
return new LatLon(latitude/nodes.size(), longitude/nodes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LatLon getLatLon(Node n){
|
||||||
|
return new LatLon(n.getLatitude(), n.getLongitude());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LatLon getWeightCenter(Way way, Map<Long, LatLon> nodes){
|
||||||
|
List<WayNode> wayNodes = way.getWayNodes();
|
||||||
|
ArrayList<LatLon> arrayList = new ArrayList<LatLon>(wayNodes.size());
|
||||||
|
for(WayNode n : wayNodes){
|
||||||
|
if(nodes.containsKey(n.getNodeId())){
|
||||||
|
arrayList.add(nodes.get(n.getNodeId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getWeightCenter(arrayList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LatLon getWeightCenterForNodes(Way way, Map<Long, Node> nodes){
|
||||||
|
List<WayNode> wayNodes = way.getWayNodes();
|
||||||
|
ArrayList<Node> arrayList = new ArrayList<Node>(wayNodes.size());
|
||||||
|
for(WayNode n : wayNodes){
|
||||||
|
if(nodes.containsKey(n.getNodeId())){
|
||||||
|
arrayList.add(nodes.get(n.getNodeId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getWeightCenterForNodes(arrayList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets distance in meters
|
||||||
|
*/
|
||||||
|
public static double getDistance(LatLon l1, LatLon l2){
|
||||||
|
return getDistance(l1, l2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Theses methods operate with degrees (evaluating tiles & vice versa)
|
||||||
|
* degree longitude measurements (-180, 180) [27.56 Minsk]
|
||||||
|
// degree latitude measurements (90, -90) [53.9]
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO check boundaries
|
||||||
|
public static double getTileNumberX(int zoom, double longitude){
|
||||||
|
int n = 1 << zoom;
|
||||||
|
return (longitude + 180d)/360d * n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getTileNumberY(int zoom, double latitude){
|
||||||
|
int n = 1 << zoom;
|
||||||
|
double eval = Math.log( Math.tan(Math.toRadians(latitude)) + 1/Math.cos(Math.toRadians(latitude)) );
|
||||||
|
return (1 - eval / Math.PI) / 2 * n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getLongitudeFromTile(int zoom, double x) {
|
||||||
|
return x / (1 << zoom) * 360.0 - 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static double getLatitudeFromTile(int zoom, double y){
|
||||||
|
return Math.atan(Math.sinh(Math.PI * (1 - 2 * y / (1 << zoom)))) * 180d / Math.PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEmpty(String s){
|
||||||
|
return s == null || s.length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean objectEquals(Object a, Object b){
|
||||||
|
if(a == null){
|
||||||
|
return b == null;
|
||||||
|
} else {
|
||||||
|
return a.equals(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean tag(Entity e, String name, String value){
|
||||||
|
String tag = getTag(e, name);
|
||||||
|
return value.equals(tag);
|
||||||
|
}
|
||||||
|
}
|
78
DataExtractionOSM/src/com/anvisics/data/City.java
Normal file
78
DataExtractionOSM/src/com/anvisics/data/City.java
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package com.anvisics.data;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Entity;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
|
||||||
|
|
||||||
|
import com.anvisics.NodeUtil;
|
||||||
|
import com.anvisics.NodeUtil.LatLon;
|
||||||
|
|
||||||
|
public class City {
|
||||||
|
|
||||||
|
public enum CityType {
|
||||||
|
CITY(10000), TOWN(5000), VILLAGE(1000), HAMLET(300), SUBURB(300);
|
||||||
|
|
||||||
|
private double radius;
|
||||||
|
private CityType(double radius){
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRadius() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Node el;
|
||||||
|
private CityType type = null;
|
||||||
|
private Map<String, Street> streets = new TreeMap<String, Street>();
|
||||||
|
|
||||||
|
public City(Node el){
|
||||||
|
this.el = el;
|
||||||
|
String place = NodeUtil.getTag(el, "place");
|
||||||
|
for(CityType t : CityType.values()){
|
||||||
|
if(t.name().equalsIgnoreCase(place)){
|
||||||
|
type = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Street registerBuilding(LatLon point, Entity e){
|
||||||
|
String number = NodeUtil.getTag(e, "addr:housenumber");
|
||||||
|
String street = NodeUtil.getTag(e, "addr:street");
|
||||||
|
if( street != null && number != null){
|
||||||
|
if(!streets.containsKey(street)){
|
||||||
|
streets.put(street, new Street(street));
|
||||||
|
}
|
||||||
|
streets.get(street).registerBuilding(point, e);
|
||||||
|
return streets.get(street);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getName(){
|
||||||
|
return NodeUtil.getTag(el, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public CityType getType(){
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getNode(){
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Street> getStreets(){
|
||||||
|
return streets.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "City [" +type+"] " + getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
134
DataExtractionOSM/src/com/anvisics/data/DataTileManager.java
Normal file
134
DataExtractionOSM/src/com/anvisics/data/DataTileManager.java
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
package com.anvisics.data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.anvisics.NodeUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param <T> - object to store in that manager
|
||||||
|
*/
|
||||||
|
public class DataTileManager<T> {
|
||||||
|
|
||||||
|
private int zoom = 15;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* map for objects stores as 'xTile_yTile' -> List<T>
|
||||||
|
*/
|
||||||
|
private Map<String, List<T>> objects = new HashMap<String, List<T>>();
|
||||||
|
|
||||||
|
public int getZoom() {
|
||||||
|
return zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZoom(int zoom) {
|
||||||
|
// TODO !!! it is required to reindex all stored objects
|
||||||
|
if(!objects.isEmpty()){
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
this.zoom = zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putObjects(int tx, int ty, List<T> r){
|
||||||
|
if(objects.containsKey(evTile(tx, ty))){
|
||||||
|
r.addAll(objects.get(evTile(tx, ty)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depth of the neighbor tile to visit
|
||||||
|
* returns not exactly sorted list,
|
||||||
|
* however the first objects are from closer tile than last
|
||||||
|
*/
|
||||||
|
public List<T> getClosestObjects(double latitude, double longitude, int depth){
|
||||||
|
int tileX = (int) NodeUtil.getTileNumberX(zoom, longitude);
|
||||||
|
int tileY = (int) NodeUtil.getTileNumberY(zoom, latitude);
|
||||||
|
List<T> result = new ArrayList<T>();
|
||||||
|
|
||||||
|
|
||||||
|
putObjects(tileX, tileY, result);
|
||||||
|
|
||||||
|
// that's very difficult way visiting node :
|
||||||
|
// similar to visit like spiral
|
||||||
|
// however the simplest way could visit by matrix & after that sort tiles by distance (that's less efficient)
|
||||||
|
|
||||||
|
// go through circle
|
||||||
|
for (int i = 1; i <= depth; i++) {
|
||||||
|
|
||||||
|
// goes à
|
||||||
|
for (int j = 0; j <= i; j++) {
|
||||||
|
// left & right
|
||||||
|
int dx = j == 0 ? 0 : -1;
|
||||||
|
for (; dx < 1 || (j < i && dx == 1); dx += 2) {
|
||||||
|
// north
|
||||||
|
putObjects(tileX + dx * j, tileY + i, result);
|
||||||
|
// east
|
||||||
|
putObjects(tileX + i, tileY - dx * j, result);
|
||||||
|
// south
|
||||||
|
putObjects(tileX - dx * j, tileY - i, result);
|
||||||
|
// west
|
||||||
|
putObjects(tileX - i, tileY + dx * j, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String evTile(int tileX, int tileY){
|
||||||
|
return tileX +"_"+tileY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String evaluateTile(double latitude, double longitude){
|
||||||
|
int tileX = (int) NodeUtil.getTileNumberX(zoom, longitude);
|
||||||
|
int tileY = (int) NodeUtil.getTileNumberY(zoom, latitude);
|
||||||
|
return evTile(tileX, tileY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String registerObject(double latitude, double longitude, T object){
|
||||||
|
String tile = evaluateTile(latitude, longitude);
|
||||||
|
if(!objects.containsKey(tile)){
|
||||||
|
objects.put(tile, new ArrayList<T>());
|
||||||
|
}
|
||||||
|
objects.get(tile).add(object);
|
||||||
|
return tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// testing way to search
|
||||||
|
public static void print(int x, int y){
|
||||||
|
System.out.println(x + (y-1)*5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int tileX = 3;
|
||||||
|
int tileY = 3;
|
||||||
|
int depth = 3;
|
||||||
|
for(int i=1; i<=depth; i++){
|
||||||
|
|
||||||
|
// goes à
|
||||||
|
for(int j=0; j<=i; j++){
|
||||||
|
// left & right
|
||||||
|
int dx = j==0 ? 0 : -1;
|
||||||
|
for(; dx < 1 || (j < i && dx == 1); dx +=2){
|
||||||
|
// north
|
||||||
|
print(tileX + dx * j, tileY + i);
|
||||||
|
// east
|
||||||
|
print(tileX + i, tileY - dx *j);
|
||||||
|
// south
|
||||||
|
print(tileX - dx * j, tileY - i);
|
||||||
|
// west
|
||||||
|
print(tileX - i, tileY + dx *j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
109
DataExtractionOSM/src/com/anvisics/data/Region.java
Normal file
109
DataExtractionOSM/src/com/anvisics/data/Region.java
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
package com.anvisics.data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Entity;
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
|
||||||
|
|
||||||
|
import com.anvisics.NodeUtil;
|
||||||
|
import com.anvisics.NodeUtil.LatLon;
|
||||||
|
import com.anvisics.data.City.CityType;
|
||||||
|
|
||||||
|
public class Region {
|
||||||
|
private Entity entity;
|
||||||
|
|
||||||
|
private DataTileManager<Node> amenities = new DataTileManager<Node>();
|
||||||
|
|
||||||
|
private Map<CityType, Collection<City>> cities = new HashMap<CityType, Collection<City>>();
|
||||||
|
{
|
||||||
|
for(CityType type : CityType.values()){
|
||||||
|
cities.put(type, new ArrayList<City>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Region(Entity entity){
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setEntity(Entity e){
|
||||||
|
this.entity = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(){
|
||||||
|
return entity == null ? "" : NodeUtil.getTag(entity, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<City> getCitiesByType(CityType type){
|
||||||
|
return cities.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<City> getCitiesByName(String name){
|
||||||
|
return getCityByName(name, true, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<City> getSuggestedCities(String name, int number){
|
||||||
|
return getCityByName(name, false, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<City> getCityByName(String name, boolean exactMatch, int number){
|
||||||
|
List<City> l = new ArrayList<City>();
|
||||||
|
for(CityType type : CityType.values()){
|
||||||
|
for(City c : cities.get(type)){
|
||||||
|
if( (exactMatch && c.getName().equalsIgnoreCase(name)) ||
|
||||||
|
(!exactMatch && c.getName().toLowerCase().startsWith(name.toLowerCase())
|
||||||
|
)){
|
||||||
|
l.add(c);
|
||||||
|
if(l.size() >= number){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public City getClosestCity(LatLon point){
|
||||||
|
City closest = null;
|
||||||
|
double relDist = Double.POSITIVE_INFINITY;
|
||||||
|
for(CityType t : CityType.values()){
|
||||||
|
for(City c : cities.get(t)){
|
||||||
|
double rel = NodeUtil.getDistance(c.getNode(), point) / t.getRadius();
|
||||||
|
if(rel < 1) {
|
||||||
|
return c; // we are in that city
|
||||||
|
}
|
||||||
|
if(rel < relDist){
|
||||||
|
closest = c;
|
||||||
|
relDist = rel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Node> getClosestAmenities(double latitude, double longitude){
|
||||||
|
return amenities.getClosestObjects(latitude, longitude, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerAmenity(Node n){
|
||||||
|
amenities.registerObject(n.getLatitude(), n.getLongitude(), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
public City registerCity(Node c){
|
||||||
|
City city = new City(c);
|
||||||
|
if(city.getType() != null && !NodeUtil.isEmpty(city.getName())){
|
||||||
|
cities.get(city.getType()).add(city);
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
36
DataExtractionOSM/src/com/anvisics/data/Street.java
Normal file
36
DataExtractionOSM/src/com/anvisics/data/Street.java
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package com.anvisics.data;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.openstreetmap.osmosis.core.domain.v0_6.Entity;
|
||||||
|
|
||||||
|
import com.anvisics.NodeUtil.LatLon;
|
||||||
|
|
||||||
|
public class Street {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private Map<Entity, LatLon> buildings = new HashMap<Entity, LatLon>();
|
||||||
|
|
||||||
|
public Street(String name){
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerBuilding(LatLon point, Entity e){
|
||||||
|
buildings.put(e, point);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Entity> getBuildings() {
|
||||||
|
return buildings.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LatLon getLocationBuilding(Entity e){
|
||||||
|
return buildings.get(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue