initial import

git-svn-id: https://osmand.googlecode.com/svn/trunk@3 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-04-26 15:20:50 +00:00
parent 24df06a387
commit 2b43c07373
27 changed files with 2002 additions and 0 deletions

View 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
View 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>

View 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>

View 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

View 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;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View 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>

View 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>

View 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>

View 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>

View 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);
}
}

View file

@ -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));
}
}

View 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;
}
}
}

View 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>

View 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>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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";
}

View 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);
}
}
}

View 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);
}
}
}

View 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);
}
}

View 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();
}
}

View 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);
}
}
}
}
}

View 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;
}
}

View 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;
}
}