diff --git a/BatteryLifeLog/.classpath b/BatteryLifeLog/.classpath new file mode 100644 index 0000000000..6e9239ff0d --- /dev/null +++ b/BatteryLifeLog/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/BatteryLifeLog/.project b/BatteryLifeLog/.project new file mode 100644 index 0000000000..e28b3c592d --- /dev/null +++ b/BatteryLifeLog/.project @@ -0,0 +1,33 @@ + + + BatteryLifeLog + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/BatteryLifeLog/AndroidManifest.xml b/BatteryLifeLog/AndroidManifest.xml new file mode 100644 index 0000000000..c2bb805fb5 --- /dev/null +++ b/BatteryLifeLog/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BatteryLifeLog/default.properties b/BatteryLifeLog/default.properties new file mode 100644 index 0000000000..a1ef8e9ff4 --- /dev/null +++ b/BatteryLifeLog/default.properties @@ -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 diff --git a/BatteryLifeLog/gen/com/anvisics/battery/R.java b/BatteryLifeLog/gen/com/anvisics/battery/R.java new file mode 100644 index 0000000000..b9b27c67fe --- /dev/null +++ b/BatteryLifeLog/gen/com/anvisics/battery/R.java @@ -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; + } +} diff --git a/BatteryLifeLog/res/drawable/icon.png b/BatteryLifeLog/res/drawable/icon.png new file mode 100644 index 0000000000..a07c69fa5a Binary files /dev/null and b/BatteryLifeLog/res/drawable/icon.png differ diff --git a/BatteryLifeLog/res/layout/main.xml b/BatteryLifeLog/res/layout/main.xml new file mode 100644 index 0000000000..3155ab9952 --- /dev/null +++ b/BatteryLifeLog/res/layout/main.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + diff --git a/BatteryLifeLog/res/layout/mytext.xml b/BatteryLifeLog/res/layout/mytext.xml new file mode 100644 index 0000000000..5ff9c5ede0 --- /dev/null +++ b/BatteryLifeLog/res/layout/mytext.xml @@ -0,0 +1,6 @@ + + + diff --git a/BatteryLifeLog/res/menu/main_menu.xml b/BatteryLifeLog/res/menu/main_menu.xml new file mode 100644 index 0000000000..991369eb0b --- /dev/null +++ b/BatteryLifeLog/res/menu/main_menu.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/BatteryLifeLog/res/values/strings.xml b/BatteryLifeLog/res/values/strings.xml new file mode 100644 index 0000000000..968c9b1137 --- /dev/null +++ b/BatteryLifeLog/res/values/strings.xml @@ -0,0 +1,9 @@ + + + Hello World, BatteryViewActivity! + BatteryLifeLog +Запустить сервис +Остановить сервис +#FFFFFF +Batter Log service + diff --git a/BatteryLifeLog/src/com/anvisics/battery/BatteryLogService.java b/BatteryLifeLog/src/com/anvisics/battery/BatteryLogService.java new file mode 100644 index 0000000000..f3a18b077b --- /dev/null +++ b/BatteryLifeLog/src/com/anvisics/battery/BatteryLogService.java @@ -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 entries = new ArrayList(); + + + 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 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); + } + +} diff --git a/BatteryLifeLog/src/com/anvisics/battery/BatteryStatusReceiver.java b/BatteryLifeLog/src/com/anvisics/battery/BatteryStatusReceiver.java new file mode 100644 index 0000000000..3015d5d96c --- /dev/null +++ b/BatteryLifeLog/src/com/anvisics/battery/BatteryStatusReceiver.java @@ -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)); + + } + +} diff --git a/BatteryLifeLog/src/com/anvisics/battery/BatteryViewActivity.java b/BatteryLifeLog/src/com/anvisics/battery/BatteryViewActivity.java new file mode 100644 index 0000000000..7dee2d865f --- /dev/null +++ b/BatteryLifeLog/src/com/anvisics/battery/BatteryViewActivity.java @@ -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 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 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(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 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; + } + } + + +} \ No newline at end of file diff --git a/DataExtractionOSM/.classpath b/DataExtractionOSM/.classpath new file mode 100644 index 0000000000..ca43d9b9db --- /dev/null +++ b/DataExtractionOSM/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/DataExtractionOSM/.project b/DataExtractionOSM/.project new file mode 100644 index 0000000000..b5b0d31f6a --- /dev/null +++ b/DataExtractionOSM/.project @@ -0,0 +1,17 @@ + + + DataExtractionOSM + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/DataExtractionOSM/lib/bzip2-20090327.jar b/DataExtractionOSM/lib/bzip2-20090327.jar new file mode 100644 index 0000000000..7721279538 Binary files /dev/null and b/DataExtractionOSM/lib/bzip2-20090327.jar differ diff --git a/DataExtractionOSM/lib/commons-logging-1.1.1.jar b/DataExtractionOSM/lib/commons-logging-1.1.1.jar new file mode 100644 index 0000000000..1deef144cb Binary files /dev/null and b/DataExtractionOSM/lib/commons-logging-1.1.1.jar differ diff --git a/DataExtractionOSM/lib/jpf.jar b/DataExtractionOSM/lib/jpf.jar new file mode 100644 index 0000000000..6d46124c5c Binary files /dev/null and b/DataExtractionOSM/lib/jpf.jar differ diff --git a/DataExtractionOSM/lib/osmosis-0.32.jar b/DataExtractionOSM/lib/osmosis-0.32.jar new file mode 100644 index 0000000000..d4d05d1b72 Binary files /dev/null and b/DataExtractionOSM/lib/osmosis-0.32.jar differ diff --git a/DataExtractionOSM/src/com/anvisics/Constants.java b/DataExtractionOSM/src/com/anvisics/Constants.java new file mode 100644 index 0000000000..c908ba7be0 --- /dev/null +++ b/DataExtractionOSM/src/com/anvisics/Constants.java @@ -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"; +} diff --git a/DataExtractionOSM/src/com/anvisics/DataExtraction.java b/DataExtractionOSM/src/com/anvisics/DataExtraction.java new file mode 100644 index 0000000000..ead4249b6b --- /dev/null +++ b/DataExtractionOSM/src/com/anvisics/DataExtraction.java @@ -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 places = new ArrayList(); + final Map nodes = new HashMap(); + final List buildings = new ArrayList(); + final List amenities = new ArrayList(); + + + // highways count + final Map mapWays = new LinkedHashMap(); + + 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 closestAmenities = reg.getClosestAmenities(newLatitude, newLongitude); + Collections.sort(closestAmenities, new Comparator(){ + @Override + public int compare(Node o1, Node o2) { + return Double.compare(NodeUtil.getDistance(o1, newLatitude, newLongitude), + NodeUtil.getDistance(o2, newLatitude, newLongitude)); + } + + }); + + Map> filter = new TreeMap>(); + for(Node n : closestAmenities){ + String type = NodeUtil.getTag(n, "amenity"); + if(!filter.containsKey(type)){ + filter.put(type, new ArrayList()); + } + 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 consists = new LinkedHashMap(); +// for(Node n : filter.get(s)){ +// consists.put(n, null); +// } +// for(int i=0; i 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); + } + } + +} diff --git a/DataExtractionOSM/src/com/anvisics/MapPanel.java b/DataExtractionOSM/src/com/anvisics/MapPanel.java new file mode 100644 index 0000000000..bc76679b03 --- /dev/null +++ b/DataExtractionOSM/src/com/anvisics/MapPanel.java @@ -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 listeners = new ArrayList(); + + 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 cache = new HashMap(); + 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 list = new ArrayList(cache.keySet()); + for(int i=0; i= 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); + } + + } + +} diff --git a/DataExtractionOSM/src/com/anvisics/NodeUtil.java b/DataExtractionOSM/src/com/anvisics/NodeUtil.java new file mode 100644 index 0000000000..8bd78a6f5a --- /dev/null +++ b/DataExtractionOSM/src/com/anvisics/NodeUtil.java @@ -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 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 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 nodes){ + List wayNodes = way.getWayNodes(); + ArrayList arrayList = new ArrayList(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 nodes){ + List wayNodes = way.getWayNodes(); + ArrayList arrayList = new ArrayList(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); + } +} diff --git a/DataExtractionOSM/src/com/anvisics/data/City.java b/DataExtractionOSM/src/com/anvisics/data/City.java new file mode 100644 index 0000000000..ba9a21c9ad --- /dev/null +++ b/DataExtractionOSM/src/com/anvisics/data/City.java @@ -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 streets = new TreeMap(); + + 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 getStreets(){ + return streets.values(); + } + + @Override + public String toString() { + return "City [" +type+"] " + getName(); + } + +} diff --git a/DataExtractionOSM/src/com/anvisics/data/DataTileManager.java b/DataExtractionOSM/src/com/anvisics/data/DataTileManager.java new file mode 100644 index 0000000000..35d1111979 --- /dev/null +++ b/DataExtractionOSM/src/com/anvisics/data/DataTileManager.java @@ -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 - object to store in that manager + */ +public class DataTileManager { + + private int zoom = 15; + + /** + * map for objects stores as 'xTile_yTile' -> List + */ + private Map> objects = new HashMap>(); + + 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 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 getClosestObjects(double latitude, double longitude, int depth){ + int tileX = (int) NodeUtil.getTileNumberX(zoom, longitude); + int tileY = (int) NodeUtil.getTileNumberY(zoom, latitude); + List result = new ArrayList(); + + + 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()); + } + 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); + } + } + } + } + + + + +} diff --git a/DataExtractionOSM/src/com/anvisics/data/Region.java b/DataExtractionOSM/src/com/anvisics/data/Region.java new file mode 100644 index 0000000000..d9f91901d7 --- /dev/null +++ b/DataExtractionOSM/src/com/anvisics/data/Region.java @@ -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 amenities = new DataTileManager(); + + private Map> cities = new HashMap>(); + { + for(CityType type : CityType.values()){ + cities.put(type, new ArrayList()); + } + } + + + 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 getCitiesByType(CityType type){ + return cities.get(type); + } + + public Collection getCitiesByName(String name){ + return getCityByName(name, true, Integer.MAX_VALUE); + } + + public Collection getSuggestedCities(String name, int number){ + return getCityByName(name, false, number); + } + + protected Collection getCityByName(String name, boolean exactMatch, int number){ + List l = new ArrayList(); + 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 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; + } + + + + +} diff --git a/DataExtractionOSM/src/com/anvisics/data/Street.java b/DataExtractionOSM/src/com/anvisics/data/Street.java new file mode 100644 index 0000000000..5f959c53b6 --- /dev/null +++ b/DataExtractionOSM/src/com/anvisics/data/Street.java @@ -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 buildings = new HashMap(); + + public Street(String name){ + this.name = name; + } + + public void registerBuilding(LatLon point, Entity e){ + buildings.put(e, point); + } + + public Set getBuildings() { + return buildings.keySet(); + } + + public LatLon getLocationBuilding(Entity e){ + return buildings.get(e); + } + + public String getName() { + return name; + } + +}