aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--.project33
-rw-r--r--AndroidManifest.xml40
-rw-r--r--README7
-rw-r--r--assets/building_estates.csv337
-rw-r--r--assets/buildings_points.csv261
-rw-r--r--assets/bus_stops.csv1410
-rw-r--r--assets/data.dbbin0 -> 142336 bytes
-rw-r--r--assets/routes.csv6
-rw-r--r--assets/routestops.csv328
-rw-r--r--assets/sites.csv22
-rw-r--r--gen/net/cbaines/suma/R.java140
-rw-r--r--lint.xml3
-rw-r--r--proguard.cfg40
-rw-r--r--project.properties11
-rw-r--r--res/drawable-hdpi/building.pngbin0 -> 3084 bytes
-rw-r--r--res/drawable-hdpi/building_fav.pngbin0 -> 3197 bytes
-rw-r--r--res/drawable-hdpi/busstop.pngbin0 -> 5175 bytes
-rw-r--r--res/drawable-hdpi/busstop_fav.pngbin0 -> 4838 bytes
-rw-r--r--res/drawable-hdpi/ic_menu_star.pngbin0 -> 1173 bytes
-rw-r--r--res/drawable-ldpi/building.pngbin0 -> 1193 bytes
-rw-r--r--res/drawable-ldpi/building_fav.pngbin0 -> 1172 bytes
-rw-r--r--res/drawable-ldpi/busstop.pngbin0 -> 1788 bytes
-rw-r--r--res/drawable-ldpi/busstop_fav.pngbin0 -> 1669 bytes
-rw-r--r--res/drawable-ldpi/ic_menu_star.pngbin0 -> 879 bytes
-rw-r--r--res/drawable-mdpi/building.pngbin0 -> 1735 bytes
-rw-r--r--res/drawable-mdpi/building_fav.pngbin0 -> 1604 bytes
-rw-r--r--res/drawable-mdpi/busstop.pngbin0 -> 2437 bytes
-rw-r--r--res/drawable-mdpi/busstop_fav.pngbin0 -> 2306 bytes
-rw-r--r--res/drawable-mdpi/ic_menu_star.pngbin0 -> 1370 bytes
-rw-r--r--res/drawable-xhdpi/building.pngbin0 -> 4486 bytes
-rw-r--r--res/drawable-xhdpi/building_fav.pngbin0 -> 4451 bytes
-rw-r--r--res/drawable-xhdpi/busstop.pngbin0 -> 7553 bytes
-rw-r--r--res/drawable-xhdpi/busstop_fav.pngbin0 -> 7078 bytes
-rw-r--r--res/drawable-xhdpi/ic_menu_star.pngbin0 -> 1264 bytes
-rw-r--r--res/drawable/u1_back.xml14
-rw-r--r--res/drawable/u1n_back.xml14
-rw-r--r--res/drawable/u2_back.xml14
-rw-r--r--res/drawable/u6_back.xml14
-rw-r--r--res/drawable/u9_back.xml14
-rw-r--r--res/layout/about_dialog.xml33
-rw-r--r--res/layout/bustimes.xml120
-rw-r--r--res/layout/donate_dialog.xml49
-rw-r--r--res/layout/favourite_dialog.xml22
-rw-r--r--res/layout/find.xml36
-rw-r--r--res/layout/main.xml15
-rw-r--r--res/layout/view_child_row.xml23
-rw-r--r--res/layout/view_dialog.xml16
-rw-r--r--res/layout/view_group_row.xml16
-rw-r--r--res/menu/map_menu.xml16
-rw-r--r--res/raw/u1.gpx824
-rw-r--r--res/raw/u1e.gpx244
-rw-r--r--res/raw/u1n.gpx374
-rw-r--r--res/raw/u2.gpx399
-rw-r--r--res/raw/u6.gpx750
-rw-r--r--res/raw/u9.gpx378
-rw-r--r--res/values/strings.xml84
-rw-r--r--res/xml/preferences.xml23
-rw-r--r--src/net/cbaines/suma/AboutActivity.java149
-rw-r--r--src/net/cbaines/suma/Building.java64
-rw-r--r--src/net/cbaines/suma/BuildingNumOverlay.java273
-rw-r--r--src/net/cbaines/suma/Bus.java57
-rw-r--r--src/net/cbaines/suma/BusRoute.java186
-rw-r--r--src/net/cbaines/suma/BusStop.java57
-rw-r--r--src/net/cbaines/suma/BusStopOverlay.java309
-rw-r--r--src/net/cbaines/suma/BusStopView.java34
-rw-r--r--src/net/cbaines/suma/BusTimeActivity.java247
-rw-r--r--src/net/cbaines/suma/DataHandler.java114
-rw-r--r--src/net/cbaines/suma/DataManager.java726
-rw-r--r--src/net/cbaines/suma/DatabaseHelper.java279
-rw-r--r--src/net/cbaines/suma/DonateDialog.java92
-rw-r--r--src/net/cbaines/suma/FavouriteDialog.java130
-rw-r--r--src/net/cbaines/suma/FindActivity.java399
-rw-r--r--src/net/cbaines/suma/POI.java94
-rw-r--r--src/net/cbaines/suma/POIArrayAdapter.java78
-rw-r--r--src/net/cbaines/suma/POIDistanceComparator.java50
-rw-r--r--src/net/cbaines/suma/POIFavouriteComparator.java40
-rw-r--r--src/net/cbaines/suma/POIView.java116
-rw-r--r--src/net/cbaines/suma/Polygon.java53
-rw-r--r--src/net/cbaines/suma/PreferencesActivity.java39
-rw-r--r--src/net/cbaines/suma/RouteColorConstants.java30
-rw-r--r--src/net/cbaines/suma/RouteOverlayItem.java37
-rw-r--r--src/net/cbaines/suma/RouteStops.java58
-rw-r--r--src/net/cbaines/suma/Site.java55
-rw-r--r--src/net/cbaines/suma/SouthamptonUniversityMapActivity.java1405
-rw-r--r--src/net/cbaines/suma/Stop.java78
-rw-r--r--src/net/cbaines/suma/StopView.java98
-rw-r--r--src/net/cbaines/suma/StringDistanceComparator.java132
-rw-r--r--src/net/cbaines/suma/Timetable.java31
-rw-r--r--src/net/cbaines/suma/TimetableAdapter.java60
-rw-r--r--src/net/cbaines/suma/Util.java95
-rw-r--r--src/net/cbaines/suma/Waypoint.java42
92 files changed, 11846 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7cffa4c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+bin/
+*.class
+*.temp
+*.bak
+*~
+*.tmp
+.settings/
+.metadata/
+.classpath
diff --git a/.project b/.project
new file mode 100644
index 0000000..4ea7f3b
--- /dev/null
+++ b/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Southampton University Map</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>
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..6069704
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="net.cbaines.suma"
+ android:versionCode="1"
+ android:versionName="0.1 (alpha)" >
+
+ <uses-sdk android:minSdkVersion="7" />
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application
+ android:icon="@drawable/busstop"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".SouthamptonUniversityMapActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="FindActivity" >
+ </activity>
+ <activity android:name="BusTimeActivity" >
+ </activity>
+ <activity android:name="AboutActivity" >
+ </activity>
+ <activity
+ android:name=".PreferencesActivity"
+ android:label="@string/preferences" >
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 0000000..226651d
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
+Southampton University Map
+
+To build, you must have avalible ormlite, osmdroid and slf4j-android. As jars, these would be:
+ormlite-android-4.30.jar
+ormlite-core-4.30.jar
+osmdroid-android-3.0.6.jar
+slf4j-android-1.5.8.jar
diff --git a/assets/building_estates.csv b/assets/building_estates.csv
new file mode 100644
index 0000000..febda75
--- /dev/null
+++ b/assets/building_estates.csv
@@ -0,0 +1,337 @@
+Name,ID,Site,Residential
+Building 1,1,1,NR
+Building 2,2,1,NR
+Law,4,1,NR
+Eustice,5,1,NR
+Nuffield Theatre,6,1,NR
+Lanchester,7,1,NR
+A B Woods Laboratory,8,1,NR
+Engineering Workshops,9,1,NR
+Energy Centre (CHP),11,1,NR
+Tizard,13,1,NR
+Workshop adjacent to B13,13A,1,NR
+Wolfson/Rayleigh,15,1,NR
+Building 16,16,1,NR
+R J Mitchell Wind Tunnel,17,1,NR
+Jubilee Sports Complex,18,1,NR
+ISVR,19,1,NR
+High Voltage Laboratory,20,1,NR
+Faraday,21,1,NR
+Civil Eng Temp Accommodation,22,1,NR
+EScience Building,25,1,NR
+Building 26,26,1,NR
+Chemistry,27,1,NR
+Froude,28,1,NR
+Graham Hills,29,1,NR
+Synthetic Chemistry,30,1,NR
+Combinatorial Chemistry,30A,1,NR
+Hartley Store,31,1,NR
+EEE Building,32,1,NR
+Estates (Maintenance),33,1,NR
+Education,34,1,NR
+David Kiddle,35,1,NR
+Library (inc. blds 10 12 & 14),36,1,NR
+George Thomas,37,1,NR
+George Thomas Building Exten,37A,1,NR
+Staff Social Centre,38,1,NR
+Soton Stat Sci Res Institute,39,1,NR
+West Bld & Staff Social Centre,40,1,NR
+Day Nursery,41,1,NR
+Students' Union/Refectory,42,1,NR
+Shackleton,44,1,NR
+Geodata Institute,44A,1,NR
+Potting Shed behind B44,44B,1,NR
+Health Profs & Rehab Sciences,45,1,NR
+Physics,46,1,NR
+University Health Centre,48,1,NR
+John Hansard Gallery,50,1,NR
+Turner Sims Concert Hall,52,1,NR
+New Mountbatten,53,1,NR
+Mathematics,54,1,NR
+Human Performance Laboratory,56,1,NR
+Students' Union Retail Centre,57,1,NR
+Murray,58,1,NR
+Building 58A,58A,1,NR
+New Zepler,59,1,NR
+Gower,60,1,NR
+Ship Science Store,61,1,NR
+Nightingale,67,1,NR
+Life Sciences,85,1,NR
+Portacabin by Gower Building,86,1,NR
+Interchange Kiosk,115,1,NR
+26 University Road,1050,1,NR
+28 University Road,1051,1,NR
+31 University Road,1101,1,NR
+39 University Road,1102,1,NR
+41 University Rd - Chaplaincy,1104,1,NR
+43 University Road,1105,1,NR
+45 University Road,1106,1,NR
+47 University Road,1107,1,NR
+130 Burgess Road,1220,1,NR
+134 Burgess Road,1221,1,NR
+136 Burgess Road,1222,1,NR
+44 Chamberlain Road,1419,1,NR
+46 Chamberlain Road S/Union,1420,1,NR
+P/kabin Occ Health rr 26/28 UR,9014,1,NR
+Plumbers' Store behind B35,9019,1,NR
+8 Chamberlain Road,1401,1,R
+10 Chamberlain Road,1402,1,R
+12 Chamberlain Road,1403,1,R
+14 Chamberlain Road,1404,1,R
+16 Chamberlain Road,1405,1,R
+18 Chamberlain Road,1406,1,R
+20 Chamberlain Road,1407,1,R
+22 Chamberlain Road,1408,1,R
+24 Chamberlain Road,1409,1,R
+26 Chamberlain Road,1410,1,R
+28 Chamberlain Road,1411,1,R
+30 Chamberlain Road,1412,1,R
+32 Chamberlain Road,1413,1,R
+34 Chamberlain Road,1414,1,R
+36 Chamberlain Road,1415,1,R
+38 Chamberlain Road,1416,1,R
+40 Chamberlain Road,1417,1,R
+42 Chamberlain Road,1418,1,R
+48 Chamberlain Road,1421,1,R
+50 Chamberlain Road,1422,1,R
+52 Chamberlain Road,1423,1,R
+54 Chamberlain Road,1424,1,R
+56 Chamberlain Road,1425,1,R
+58 Chamberlain Road,1426,1,R
+17 Hartley Avenue,1501,1,R
+19 Hartley Avenue,1502,1,R
+21 Hartley Avenue,1503,1,R
+23 Hartley Avenue,1504,1,R
+25 Hartley Avenue,1505,1,R
+27 Hartley Avenue,1506,1,R
+29 Hartley Avenue,1507,1,R
+31 Hartley Avenue,1508,1,R
+65 Heatherdeane Road,1580,1,R
+62 Granby Grove,1601,1,R
+64 Granby Grove,1602,1,R
+Bassett House,1604,40,R
+Birchwood,1620,37,R
+158 Mayfield Road,1622,1,R
+185 Broadlands Road,1630,1,R
+10 Orchards Way,1640,1,R
+Oakhurst Road,73,1,R
+Boldrewood,62,2,NR
+34 Bassett Crescent East,1603,2,NR
+17 Oaklands Way,1395,2,R
+Parkes Bldg,65,3,NR
+Archaelogy (ex-Crawford),65A,3,NR
+Burgess,65B,3,NR
+16 Highfield Road,1310,3,NR
+East Site,63A,4,NR
+Terrapin,63C,4,NR
+Adminstration,63F,4,NR
+Textile Conservation Cnt,63G,4,NR
+West Site,63K,4,NR
+Students' Union,63L,4,NR
+Chilworth Estate,71,5,NR
+Chilworth Laboratories,89,5,NR
+Alpha House,92,5,NR
+3 Venture Road,96,5,NR
+Epsilon House,97,5,NR
+2 Venture Road,99,5,NR
+National Oceanography Centre,68,6,NR
+National Oceanography Centre - Block A1,68-A1,6,NR
+National Oceanography Centre - Block A6,68-A6,6,NR
+National Oceanography Centre - Block N9,68-N9,6,NR
+72 Mead Crescent,1612,8,R
+South Academic Block,9500,18,NR
+Lab & Path Block,9510,18,NR
+West Wing,9520,18,NR
+Centre Block,9530,18,NR
+P/Anne Maternity Unit,9550,18,NR
+IDS,9555,18,NR
+Duthie,9560,18,NR
+Duthie/Tenovus Link,9561,18,NR
+Tenovus,9570,18,NR
+Somers Cancer Research,9580,18,NR
+MRC Building,9581,18,NR
+Royal South Hants,9585,20,NR
+Aldermoor Health Centre,9590,19,NR
+"North Hampshire Hospital, Basingstoke",9591,21,NR
+"Royal Hampshire County Hospital, Winchester",9592,22,NR
+"St. Mary's Hospital, Portsmouth",9593,23,NR
+"St Mary's Hospital, Isle of Wight",9594,24,NR
+"Nurses' accommodation, Portsmouth",9595,25,NR
+New Sports Pavilion Wide Lane,93,39,NR
+Boat House 1,94A,8,NR
+Boat House 2,94B,8,NR
+Westsuit Drying/Store,94C,8,NR
+Store 1,94D,8,NR
+Boat House Changing Rooms,94F,8,NR
+Workshop,94G,8,NR
+Classroom,94H,8,NR
+Store 2,94J,8,NR
+Old Sports Pavilion Wide Lane,95,39,NR
+Staff P/kabin 1 Wide Lane,9001,39,NR
+P/kabin 2 rear Bld 35,9002,1,NR
+"Boiler House, Wide Lane",9003,39,NR
+Gardening Shed Wide Lane,9004,39,NR
+Changing Room 1 Wide Lane,9011,39,NR
+Changing Room 2 Wide Lane,9012,39,NR
+Unit 6 Store,150,45,NR
+Unit 12 Bindery,151,45,NR
+Unit 13 Print Centre,152,45,NR
+Highfield Hall Aubrey House,75A,56,R
+Highfield Hall Laundry,75B,56,R
+Highfield Hall Wolfe House,75C,56,R
+Glen Eyre Hall Block A Richard Newitt,73A,57,R
+Glen Eyre Hall Block B Richard Newitt,73B,57,R
+Glen Eyre Hall Bungalow 1,73B1,57,R
+Glen Eyre Bungalow 2,73B2,57,R
+Glen Eyre Bungalow 3,73B3,57,R
+Glen Eyre Hall Bungalow 4,73B4,57,R
+Glen Eyre Hall Block C Richard Newitt,73C,57,R
+Glen Eyre Hall Block D Richard Newitt,73D,57,R
+Glen Eyre Hall Block E Richard Newitt,73E,57,R
+Glen Eyre Hall Block F Richard Newitt,73F,57,R
+Glen Eyre Hall Block G Richard Newitt,73G,57,R
+Glen Eyre Hall Block H Richard Newitt,73H,57,R
+Glen Eyre Hall Block J,73J,57,R
+"Glen Eyre Hall, Chancellor's Court, Selbourne",73K,57,R
+"Glen Eyre Hall, Chancellor's Court, Jellicoe",73L,57,R
+"Glen Eyre Hall, Chancellor's Court, Roll",73M,57,R
+Block A Glen Eyre Hall Old Terrace,73N-A,57,R
+Block B Glen Eyre Hall Old Terrace,73N-B,57,R
+Block C Glen Eyre Hall Old Terrace,73N-C,57,R
+Block D Glen Eyre Hall Old Terrace,73N-D,57,R
+Block E Glen Eyre Hall Old Terrace,73N-E,57,R
+Block F Glen Eyre Hall Old Terrace,73N-F,57,R
+Block G Glen Eyre Hall Old Terrace,73N-G,57,R
+Block H Glen Eyre Hall Old Terrace,73N-H,57,R
+Block J Glen Eyre Hall Old Terrace,73N-J,57,R
+Block K Glen Eyre Hall Old Terrace,73N-K,57,R
+Glen Eyre Hall Main Building,73Q1,57,R
+Glen Eyre Hall Dining Hall,73Q2,57,R
+Glen Eyre Hall Squash Court,73S,57,R
+Glen Eyre Hall Brunei House,73T,57,R
+Glen Eyre Hall Block W,73W,57,R
+Block Q Glen Eyre Hall New Terrace,73X-Q,57,R
+Block R Glen Eyre Hall New Terrace,73X-R,57,R
+Block S Glen Eyre Hall New Terrace,73X-S,57,R
+Block T Glen Eyre Hall New Terrace,73X-T,57,R
+South Hill A,70AA,58,R
+South Hill B,70BB,58,R
+South Hill C,70CC,58,R
+Chamberlain A,70A,59,R
+Chamberlain B,70B,59,R
+Chamberlain C,70C,59,R
+Chamberlain Dining Room,70D,59,R
+Chamberlain Boiler House,70E,59,R
+Chamberlain Bin Store,70F,59,R
+50 Glen Eyre Road,1710,59,R
+Hartley Grove A,79A,60,R
+Hartley Grove B,79B,60,R
+Hartley Grove C,79C,60,R
+Beechmount House,73R,61,R
+Bencraft Court Block A,81A,62,R
+Bencraft Court Block B,81B,62,R
+Bencraft Court Block C,81C,62,R
+Bencraft Court Bar,81D,62,R
+Bencraft Court Cycle Sheds,81E,62,R
+Connaught A (Old Quad),72A1-A,63,R
+Connaught B (Old Quad),72A1-B,63,R
+Connaught C (Old Quad),72A1-C,63,R
+Connaught D (Old Quad),72A2-D,63,R
+Connaught E (Old Quad),72A2-E,63,R
+Connaught F (Old Quad),72A2-F,63,R
+Connaught G (Old Quad),72A2-G,63,R
+Connaught H (Old Quad),72A2-H,63,R
+Connaught J (New Quad),72A2-J,63,R
+Connaught K (New Quad),72A2-K,63,R
+Connaught L (New Quad),72A2-L,63,R
+Connaught Hall Squash Court,72B,63,R
+Connaught Hall Dining Room,72C,63,R
+Connaught Hall/Lobby/Laundry,72CC,63,R
+Connaught M (New Quad),72D-M,63,R
+Connaught N (New Quad),72D-N,63,R
+Connaught P (New Quad),72D-P,63,R
+Connaught Q (New Quad),72E-Q,63,R
+Connaught R (New Quad),72E-R,63,R
+Connaught S (New Quad),72F-S,63,R
+"Connaught Hall, The Bungalow",72G,63,R
+Montefiore Hall Block A,76A,64,R
+Montefiore Hall Block B,76B,64,R
+Montefiore Hall Block C,76C,64,R
+Montefiore Hall Block D,76D,64,R
+Montefiore Hall Block E,76E,64,R
+Montefiore Hall Block F,76F,64,R
+Montefiore Hall Block G,76G,64,R
+Montefiore Hall Block H,76H,64,R
+Montefiore Hall Block J,76J,64,R
+Montefiore Hall Block K,76K,64,R
+Montefiore Hall Block L,76L,64,R
+Montefiore Hall Block M,76M,64,R
+Montefiore Hall Block N,76N,64,R
+Montefiore Hall Block P,76P,64,R
+Montefiore Hall Block Q,76Q,64,R
+Montefiore Hall Block R,76R,64,R
+Montefiore Hall Block S,76S,64,R
+Montefiore Hall Social Centre,76SC,64,R
+Montefiore Hall Block T,76T,64,R
+Montefiore Hall Laundry,76U,64,R
+Montefiore Hall Block V,76V,64,R
+Montefiore Hall Block W,76W,64,R
+Montefiore Hall Block X,76X,64,R
+Montefiore Hall - Reception,76Z,64,R
+South Stoneham House,78A,65,R
+South Stoneham Tower,78B,65,R
+South Stoneham Dining Room,78C,65,R
+South Stoneham Staff Block,78D,65,R
+South Stoneham Warden's Lodge,78E,65,R
+St Margaret's Hall,77,66,R
+Gateley Hall,82A,67,R
+Romero Hall,82B,68,R
+13 Chestnut Lodge,1626,69,R
+Erasmus Park,1730,70,R
+Erasmus - House 01,1730-01,70,R
+Erasmus - House 02,1730-02,70,R
+Erasmus - House 03,1730-03,70,R
+Erasmus - House 04,1730-04,70,R
+Erasmus - House 05,1730-05,70,R
+Erasmus - House 06,1730-06,70,R
+Erasmus - House 07,1730-07,70,R
+Erasmus - House 08,1730-08,70,R
+Erasmus - House 09,1730-09,70,R
+Erasmus - House 10,1730-10,70,R
+Erasmus - House 11,1730-11,70,R
+Erasmus - House 12,1730-12,70,R
+Erasmus - House 13,1730-13,70,R
+Erasmus - House 14,1730-14,70,R
+Erasmus - House 15,1730-15,70,R
+Erasmus - House 16,1730-16,70,R
+Erasmus - House 17,1730-17,70,R
+Erasmus - House 18,1730-18,70,R
+Erasmus - Flat 19,1730-19,70,R
+Erasmus - Flat 20,1730-20,70,R
+Erasmus - Flat 21,1730-21,70,R
+Erasmus - Flat 22,1730-22,70,R
+Erasmus - Flat 23,1730-23,70,R
+Erasmus - Flat 24,1730-24,70,R
+Erasmus - Flat 25,1730-25,70,R
+Erasmus - Flat 26,1730-26,70,R
+Erasmus - Flat 27,1730-27,70,R
+Erasmus - Flat 28,1730-28,70,R
+Erasmus - Flat 29,1730-29,70,R
+Erasmus - Flat 30,1730-30,70,R
+Erasmus - Flat 31,1730-31,70,R
+Erasmus - Flat 32,1730-32,70,R
+Erasmus - Flat 33,1730-33,70,R
+Erasmus - Flat 34,1730-34,70,R
+Erasmus - Flat 35,1730-35,70,R
+Erasmus - Flat 36,1730-36,70,R
+Erasmus - Flat 37,1730-37,70,R
+Erasmus - Flat 38,1730-38,70,R
+Erasmus - Flat 39,1730-39,70,R
+Erasmus - Flat 40,1730-40,70,R
+Erasmus - Flat 41,1730-41,70,R
+24 Mead Crescent,1610,71,R
+1A Oakhurst Road,1390,73,R
+1B Oakhurst Road,1391,73,R
+18-20 Shaftesbury Avenue,165,77,R
+"1A Victoria Place, Portsmouth",166,78,R
+College Keep,123,79,NR \ No newline at end of file
diff --git a/assets/buildings_points.csv b/assets/buildings_points.csv
new file mode 100644
index 0000000..d72dd34
--- /dev/null
+++ b/assets/buildings_points.csv
@@ -0,0 +1,261 @@
+id,long,lat,source
+1,-1.3960704,50.9376734,http://os.openstreetmap.org/
+2,-1.3981275,50.9362789,http://os.openstreetmap.org/
+4,-1.3977134,50.9360909,http://os.openstreetmap.org/
+5,-1.3948313,50.9355883,http://os.openstreetmap.org/
+6,-1.3972189,50.9359585,http://os.openstreetmap.org/
+7,-1.3940282,50.9353558,http://os.openstreetmap.org/
+8,-1.3947926,50.936537,http://os.openstreetmap.org/
+9,-1.394215,50.9355501,http://os.openstreetmap.org/
+13,-1.393488,50.935551,http://os.openstreetmap.org/
+15,-1.3933722,50.9358355,http://os.openstreetmap.org/
+16,-1.3956608,50.9376285,http://os.openstreetmap.org/
+17,-1.3946145,50.9362396,http://os.openstreetmap.org/
+18,-1.3966792,50.9338813,http://os.openstreetmap.org/
+19,-1.392867,50.9355444,http://os.openstreetmap.org/
+20,-1.3951265,50.9368962,http://os.openstreetmap.org/
+21,-1.3932157,50.9351646,http://os.openstreetmap.org/
+22,-1.3941636,50.9350233,http://os.openstreetmap.org/
+25,-1.3934585,50.9347702,http://os.openstreetmap.org/
+26,-1.3941216,50.9347143,http://os.openstreetmap.org/
+27,-1.393776,50.93432,http://os.openstreetmap.org/
+28,-1.3945278,50.9346967,http://os.openstreetmap.org/
+29,-1.3939798,50.9340008,http://os.openstreetmap.org/
+30,-1.3944765,50.9343082,http://os.openstreetmap.org/
+32,-1.395905,50.9364157,http://os.openstreetmap.org/
+34,-1.395317,50.9344936,http://os.openstreetmap.org/
+35,-1.394475,50.93383,http://os.openstreetmap.org/
+36,-1.395156,50.934986,http://os.openstreetmap.org/
+37,-1.395696,50.934147,http://os.openstreetmap.org/
+38,-1.3974278,50.9354059,http://os.openstreetmap.org/
+39,-1.399298,50.936722,http://os.openstreetmap.org/
+40,-1.3973325,50.9347275,http://os.openstreetmap.org/
+41,-1.395301,50.933559,http://os.openstreetmap.org/
+42,-1.397511,50.934219,http://os.openstreetmap.org/
+44,-1.399062,50.934322,http://os.openstreetmap.org/
+45,-1.394014,50.937801,http://os.openstreetmap.org/
+46,-1.3996014,50.9348505,http://os.openstreetmap.org/
+48,-1.399485,50.935696,http://os.openstreetmap.org/
+50,-1.3994,50.936142,http://os.openstreetmap.org/
+52,-1.3988324,50.9358682,http://os.openstreetmap.org/
+53,-1.398236,50.937412,http://os.openstreetmap.org/
+54,-1.3988756,50.9362228,http://os.openstreetmap.org/
+57,-1.396755,50.934399,http://os.openstreetmap.org/
+58,-1.398697,50.936592,http://os.openstreetmap.org/
+59,-1.3977863,50.9374063,http://os.openstreetmap.org/
+60,-1.3975471,50.93774,http://os.openstreetmap.org/
+62,-1.4049952,50.9372304,http://os.openstreetmap.org/
+65,-1.402838,50.929203,http://os.openstreetmap.org/
+67,-1.3966181,50.9366885,http://os.openstreetmap.org/
+68,-1.394491,50.892773,http://os.openstreetmap.org/
+77,-1.4068368,50.920439,http://os.openstreetmap.org/
+85,-1.395323,50.936436,http://os.openstreetmap.org/
+86,-1.396765,50.93739,http://os.openstreetmap.org/
+92,-1.4255025,50.9621255,http://os.openstreetmap.org/
+93,-1.363412,50.952282,http://os.openstreetmap.org/
+96,-1.4233506,50.9619135,http://os.openstreetmap.org/
+97,-1.4250697,50.9609746,http://os.openstreetmap.org/
+99,-1.4226617,50.961019,http://os.openstreetmap.org/
+115,-1.397173,50.936291,http://os.openstreetmap.org/
+123,-1.396685,50.898575,http://os.openstreetmap.org/
+150,-1.3840867,50.9307365,http://os.openstreetmap.org/
+151,-1.3838409,50.9311694,http://os.openstreetmap.org/
+152,-1.3838018,50.9312434,http://os.openstreetmap.org/
+165,-1.3907767,50.9284882,http://os.openstreetmap.org/
+166,-1.082381,50.789497,http://os.openstreetmap.org/
+1050,-1.395323,50.933235,http://os.openstreetmap.org/
+1051,-1.395356,50.933338,http://os.openstreetmap.org/
+1101,-1.3959296,50.9330414,http://os.openstreetmap.org/
+1102,-1.3960392,50.9333389,http://os.openstreetmap.org/
+1104,-1.396101,50.9334345,http://os.openstreetmap.org/
+1105,-1.3961544,50.933516,http://os.openstreetmap.org/
+1106,-1.3962246,50.9335868,http://os.openstreetmap.org/
+1107,-1.3962471,50.9336275,http://os.openstreetmap.org/
+1220,-1.395103,50.938011,http://os.openstreetmap.org/
+1221,-1.395002,50.938026,http://os.openstreetmap.org/
+1222,-1.39495,50.938034,http://os.openstreetmap.org/
+1390,-1.400937,50.933636,http://os.openstreetmap.org/
+1391,-1.400937,50.933636,http://os.openstreetmap.org/
+1395,-1.4037955,50.9381522,http://os.openstreetmap.org/
+1401,-1.3979365,50.9330741,http://os.openstreetmap.org/
+1402,-1.3979888,50.933101,http://os.openstreetmap.org/
+1403,-1.3980886,50.9331489,http://os.openstreetmap.org/
+1404,-1.3981409,50.9331759,http://os.openstreetmap.org/
+1405,-1.3982264,50.9332298,http://os.openstreetmap.org/
+1406,-1.3982834,50.9332568,http://os.openstreetmap.org/
+1407,-1.398388,50.9333077,http://os.openstreetmap.org/
+1408,-1.3984498,50.9333406,http://os.openstreetmap.org/
+1409,-1.3985496,50.9333886,http://os.openstreetmap.org/
+1410,-1.3986066,50.9334155,http://os.openstreetmap.org/
+1411,-1.398716,50.9334605,http://os.openstreetmap.org/
+1412,-1.3987777,50.9334904,http://os.openstreetmap.org/
+1413,-1.3990059,50.9336012,http://os.openstreetmap.org/
+1414,-1.3990629,50.9336342,http://os.openstreetmap.org/
+1415,-1.3991675,50.9336731,http://os.openstreetmap.org/
+1416,-1.3992198,50.9337061,http://os.openstreetmap.org/
+1417,-1.3993291,50.933742,http://os.openstreetmap.org/
+1418,-1.3993814,50.933772,http://os.openstreetmap.org/
+1419,-1.3994954,50.9338139,http://os.openstreetmap.org/
+1420,-1.3995477,50.9338439,http://os.openstreetmap.org/
+1421,-1.3997949,50.9339487,http://os.openstreetmap.org/
+1422,-1.3998519,50.9339817,http://os.openstreetmap.org/
+1423,-1.3999612,50.9340266,http://os.openstreetmap.org/
+1424,-1.4000135,50.9340535,http://os.openstreetmap.org/
+1425,-1.4001038,50.9341015,http://os.openstreetmap.org/
+1426,-1.4001608,50.9341314,http://os.openstreetmap.org/
+1501,-1.393987,50.933098,http://os.openstreetmap.org/
+1502,-1.393974,50.933182,http://os.openstreetmap.org/
+1503,-1.393982,50.93327,http://os.openstreetmap.org/
+1504,-1.393979,50.933353,http://os.openstreetmap.org/
+1505,-1.393965,50.933445,http://os.openstreetmap.org/
+1506,-1.393944,50.933529,http://os.openstreetmap.org/
+1507,-1.393915,50.933605,http://os.openstreetmap.org/
+1508,-1.393915,50.933701,http://os.openstreetmap.org/
+1580,-1.401279,50.928944,http://os.openstreetmap.org/
+1601,-1.3925923,50.9350404,http://os.openstreetmap.org/
+1602,-1.3926691,50.9350607,http://os.openstreetmap.org/
+1603,-1.4032566,50.9380349,http://os.openstreetmap.org/
+1604,-1.4039043,50.9425216,http://os.openstreetmap.org/
+1610,-1.37853,50.936123,http://os.openstreetmap.org/
+1612,-1.380123,50.934734,http://os.openstreetmap.org/
+1622,-1.390499,50.936714,http://os.openstreetmap.org/
+1630,-1.393715,50.9369467,http://os.openstreetmap.org/
+1640,-1.398211,50.929989,http://os.openstreetmap.org/
+1710,-1.4032158,50.9421475,http://os.openstreetmap.org/
+1730,-1.3001172,51.0686667,http://os.openstreetmap.org/
+9001,-1.363689,50.951485,http://os.openstreetmap.org/
+9004,-1.363506,50.951576,http://os.openstreetmap.org/
+9011,-1.365365,50.950558,http://os.openstreetmap.org/
+9012,-1.365365,50.950558,http://os.openstreetmap.org/
+9500,-1.436441,50.932362,http://os.openstreetmap.org/
+9510,-1.435797,50.932819,http://os.openstreetmap.org/
+9520,-1.435561,50.933701,http://os.openstreetmap.org/
+9530,-1.434392,50.933247,http://os.openstreetmap.org/
+9550,-1.434907,50.935337,http://os.openstreetmap.org/
+9580,-1.433555,50.934307,http://os.openstreetmap.org/
+9585,-1.3973994,50.9125279,http://os.openstreetmap.org/
+9590,-1.427804,50.940327,http://os.openstreetmap.org/
+9591,-1.110778,51.279823,http://os.openstreetmap.org/
+9592,-1.330204,51.061089,http://os.openstreetmap.org/
+9593,-1.065159,50.800404,http://os.openstreetmap.org/
+9594,-1.300592,50.711353,http://os.openstreetmap.org/
+9595,-1.082381,50.789497,http://os.openstreetmap.org/
+37A,-1.395687,50.933811,http://os.openstreetmap.org/
+58A,-1.3980786,50.9367447,http://os.openstreetmap.org/
+63A,-1.3088779,51.0657027,http://os.openstreetmap.org/
+63C,-1.3087201,51.065325,http://os.openstreetmap.org/
+63F,-1.3097192,51.0656271,http://os.openstreetmap.org/
+63G,-1.3098995,51.0653675,http://os.openstreetmap.org/
+63K,-1.310366,51.066025,http://os.openstreetmap.org/
+63L,-1.3102375,51.066373,http://os.openstreetmap.org/
+65A,-1.403128,50.928783,http://os.openstreetmap.org/
+65B,-1.4036629,50.9288317,http://os.openstreetmap.org/
+70A,-1.4031107,50.941608,http://os.openstreetmap.org/
+70AA,-1.4025225,50.9415981,http://os.openstreetmap.org/
+70B,-1.4032631,50.9412373,http://os.openstreetmap.org/
+70BB,-1.401953,50.941452,http://os.openstreetmap.org/
+70C,-1.403592,50.941536,http://os.openstreetmap.org/
+70CC,-1.4024437,50.9412837,http://os.openstreetmap.org/
+70D,-1.4032263,50.941843,http://os.openstreetmap.org/
+70E,-1.4034784,50.9420383,http://os.openstreetmap.org/
+72A1-A,-1.374458,50.937782,http://os.openstreetmap.org/
+72A1-B,-1.374393,50.937683,http://os.openstreetmap.org/
+72A1-C,-1.374334,50.937595,http://os.openstreetmap.org/
+72A2-D,-1.37445,50.937393,http://os.openstreetmap.org/
+72A2-E,-1.37467,50.937344,http://os.openstreetmap.org/
+72A2-F,-1.374884,50.937279,http://os.openstreetmap.org/
+72A2-G,-1.375187,50.937355,http://os.openstreetmap.org/
+72A2-H,-1.375257,50.937454,http://os.openstreetmap.org/
+72A2-J,-1.375327,50.937561,http://os.openstreetmap.org/
+72A2-K,-1.374989,50.937805,http://os.openstreetmap.org/
+72A2-L,-1.375083,50.937973,http://os.openstreetmap.org/
+72C,-1.375367,50.93819,http://os.openstreetmap.org/
+72D-M,-1.37549,50.938461,http://os.openstreetmap.org/
+72D-N,-1.375209,50.938553,http://os.openstreetmap.org/
+72D-P,-1.374951,50.938625,http://os.openstreetmap.org/
+72E-Q,-1.374581,50.938484,http://os.openstreetmap.org/
+72E-R,-1.374367,50.938183,http://os.openstreetmap.org/
+72F-S,-1.375544,50.938591,http://os.openstreetmap.org/
+72G,-1.374106,50.937477,http://os.openstreetmap.org/
+73A,-1.4029587,50.943379,http://os.openstreetmap.org/
+73B,-1.4032985,50.9434045,http://os.openstreetmap.org/
+73B1,-1.400848,50.94405,http://os.openstreetmap.org/
+73B2,-1.400848,50.94405,http://os.openstreetmap.org/
+73B3,-1.400848,50.94405,http://os.openstreetmap.org/
+73B4,-1.400848,50.94405,http://os.openstreetmap.org/
+73C,-1.4032123,50.9436282,http://os.openstreetmap.org/
+73D,-1.4024566,50.9439382,http://os.openstreetmap.org/
+73E,-1.4021067,50.9438934,http://os.openstreetmap.org/
+73F,-1.402203,50.9436793,http://os.openstreetmap.org/
+73G,-1.4018785,50.9436666,http://os.openstreetmap.org/
+73H,-1.4020052,50.9441011,http://os.openstreetmap.org/
+73J,-1.401488,50.943919,http://os.openstreetmap.org/
+73K,-1.4009757,50.9432479,http://os.openstreetmap.org/
+73L,-1.4006309,50.9437049,http://os.openstreetmap.org/
+73M,-1.3998397,50.9437017,http://os.openstreetmap.org/
+73N-A,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-B,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-C,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-D,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-E,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-F,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-G,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-H,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-J,-1.402854,50.94236,http://os.openstreetmap.org/
+73N-K,-1.402854,50.94236,http://os.openstreetmap.org/
+73Q1,-1.402873,50.943848,http://os.openstreetmap.org/
+73Q2,-1.402873,50.943848,http://os.openstreetmap.org/
+73R,-1.404631,50.9434354,http://os.openstreetmap.org/
+73S,-1.401352,50.944126,http://os.openstreetmap.org/
+73T,-1.3994289,50.9431457,http://os.openstreetmap.org/
+73W,-1.4031058,50.9431776,http://os.openstreetmap.org/
+73X-Q,-1.4026798,50.9429667,http://os.openstreetmap.org/
+73X-R,-1.4023501,50.9429188,http://os.openstreetmap.org/
+73X-S,-1.4021625,50.9427239,http://os.openstreetmap.org/
+73X-T,-1.4022081,50.9424938,http://os.openstreetmap.org/
+75A,-1.4018216,50.9298947,http://os.openstreetmap.org/
+75C,-1.402665,50.9301743,http://os.openstreetmap.org/
+76A,-1.3784044,50.937321,http://os.openstreetmap.org/
+76B,-1.3778009,50.9376576,http://os.openstreetmap.org/
+76C,-1.377127,50.937645,http://os.openstreetmap.org/
+76D,-1.376708,50.937752,http://os.openstreetmap.org/
+76E,-1.376204,50.937859,http://os.openstreetmap.org/
+76F,-1.37733,50.938011,http://os.openstreetmap.org/
+76G,-1.376933,50.938107,http://os.openstreetmap.org/
+76H,-1.376402,50.938232,http://os.openstreetmap.org/
+76J,-1.377561,50.938339,http://os.openstreetmap.org/
+76K,-1.376944,50.938484,http://os.openstreetmap.org/
+76L,-1.376306,50.938629,http://os.openstreetmap.org/
+76M,-1.377389,50.938606,http://os.openstreetmap.org/
+76N,-1.376751,50.938763,http://os.openstreetmap.org/
+76P,-1.377196,50.938877,http://os.openstreetmap.org/
+76Q,-1.376536,50.939026,http://os.openstreetmap.org/
+76R,-1.376976,50.939156,http://os.openstreetmap.org/
+76S,-1.376349,50.939289,http://os.openstreetmap.org/
+76SC,-1.3780581,50.9380566,http://os.openstreetmap.org/
+76T,-1.376783,50.939426,http://os.openstreetmap.org/
+76U,-1.3780779,50.9383121,http://os.openstreetmap.org/
+76V,-1.3781373,50.937561,http://os.openstreetmap.org/
+76W,-1.3779839,50.9372773,http://os.openstreetmap.org/
+76X,-1.3784588,50.9370062,http://os.openstreetmap.org/
+76Z,-1.376976,50.937473,http://os.openstreetmap.org/
+78A,-1.376944,50.936687,http://os.openstreetmap.org/
+78B,-1.377465,50.936699,http://os.openstreetmap.org/
+78C,-1.377534,50.936543,http://os.openstreetmap.org/
+78E,-1.3759936,50.9373466,http://os.openstreetmap.org/
+79A,-1.402425,50.940872,http://os.openstreetmap.org/
+79B,-1.401899,50.940411,http://os.openstreetmap.org/
+79C,-1.401371,50.940643,http://os.openstreetmap.org/
+81A,-1.3907157,50.945967,http://os.openstreetmap.org/
+81B,-1.3904644,50.9458051,http://os.openstreetmap.org/
+81C,-1.390787,50.945606,http://os.openstreetmap.org/
+81D,-1.3909756,50.9458246,http://os.openstreetmap.org/
+81E,-1.3911761,50.9456236,http://os.openstreetmap.org/
+82A,-1.4077298,50.9169714,http://os.openstreetmap.org/
+82B,-1.4098021,50.9157541,http://os.openstreetmap.org/
+94A,-1.380039,50.934563,http://os.openstreetmap.org/
+94B,-1.380039,50.934563,http://os.openstreetmap.org/
+94C,-1.3807397,50.9337771,http://os.openstreetmap.org/
+94F,-1.380549,50.934185,http://os.openstreetmap.org/
+94G,-1.380509,50.934058,http://os.openstreetmap.org/
+94H,-1.380648,50.934078,http://os.openstreetmap.org/ \ No newline at end of file
diff --git a/assets/bus_stops.csv b/assets/bus_stops.csv
new file mode 100644
index 0000000..d51627b
--- /dev/null
+++ b/assets/bus_stops.csv
@@ -0,0 +1,1410 @@
+"Location","Description","Bay","Latitude","Longitude","",
+"HA030001","Bournemouth Rd os Asda S","","50 58.0700N","1 23.4674W","",
+"HA030002","Bournemouth Rd opp Asda N","","50 58.0846N","1 23.4723W","",
+"HA030012","Bournemouth Rd os The Hut SW","","50 58.7567N","1 23.1242W","",
+"HA030013","Bournemouth Rd opp The Hut NE","","50 58.7804N","1 23.1153W","",
+"HA030014","Winchester Rd os Chan Ford Precinct SW","","50 58.9599N","1 22.9856W","",
+"HA030015","Winchester Rd opp Chan Ford Precinct NE","","50 58.9928N","1 22.9706W","",
+"HA030039","Baddesley Rd nr Baddesley Bridge N","","50 59.7931N","1 23.9441W","",
+"HA030040","Baddesley Rd nr Baddesley Bridge S","","50 59.7192N","1 23.9468W","",
+"HA030046","Ashdown Rd nr Heathfield Rd NE","","51 0.0926N","1 23.0227W","",
+"HA030047","Ashdown Rd nr Heathfield Rd SW","","51 0.0857N","1 23.0314W","",
+"HA030066","Winchester Rd nr Peverells Wood Ave SW","","50 59.3538N","1 22.2802W","",
+"HA030067","Winchester Rd os Fryern Arcade NE","","50 59.2690N","1 22.4677W","",
+"HA030068","Winchester Rd nr Fryern Arcade SW","","50 59.2365N","1 22.5366W","",
+"HA030069","Winchester Rd nr Kings Rd SW","","50 59.1213N","1 22.7980W","",
+"HA030071","Winchester Rd nr Peverells Wood Ave NE","","50 59.3962N","1 22.2386W","",
+"HA030072","Winchester Rd os Thornden School SW","","50 59.5922N","1 21.9684W","",
+"HA030107","Bournemouth Rd nr Leigh Rd N","","50 58.5314N","1 23.2776W","",
+"HA030108","Bournemouth Rd nr Leigh Rd S","","50 58.4571N","1 23.3008W","",
+"HA030122","Chestnut Ave nr Golf Driving Range W","","50 57.7100N","1 22.7159W","",
+"HA030123","Chestnut Ave nr Golf Driving Range E","","50 57.7010N","1 22.6511W","",
+"HA030124","Chestnut Ave nr The Cricketers W","","50 57.6628N","1 22.4722W","",
+"HA030125","Chestnut Ave nr The Cricketers E","","50 57.6663N","1 22.4235W","",
+"HA030128","Nightingale Ave nr Passfield Ave E","","50 57.8230N","1 22.2582W","",
+"HA030130","Nightingale Ave nr Linnet Square W","","50 57.8171N","1 22.5787W","",
+"HA030131","Nightingale Ave nr Nightingale School E","","50 57.8844N","1 22.7504W","",
+"HA030132","Nightingale Ave nr Nightingale School W","","50 57.8911N","1 22.7819W","",
+"HA030133","Nightingale Ave nr Robin Square SW","","50 57.8384N","1 22.9236W","",
+"HA030134","Nightingale Ave nr Robin Square NE","","50 57.8331N","1 22.9356W","",
+"HA030179","Winchester Rd os Nuffield Hospital SW","","50 59.8228N","1 21.6061W","",
+"HA030180","Winchester Rd opp Nuffield Hospital NE","","50 59.8149N","1 21.6379W","",
+"HA030181","Winchester Rd opp Thornden School NE","","50 59.6679N","1 21.8878W","",
+"HA030183","Parkway Station Mitchell Way NE","","50 56.9805N","1 21.8186W","",
+"HA030184","Airport At Terminal Bldg W","","50 57.0478N","1 21.6998W","",
+"HA030186","Stoneham Ln os Trojans N","","50 57.0410N","1 22.4302W","",
+"HA030187","Stoneham Ln opp Trojans S","","50 57.0410N","1 22.4251W","",
+"HA030188","Stoneham Ln os St Nicolas Church N","","50 57.2395N","1 22.4164W","",
+"HA030189","Stoneham Ln opp St Nicolas Church S","","50 57.2389N","1 22.4104W","",
+"HA030190","Stoneham Ln os Concorde Club S","","50 57.3684N","1 22.3028W","",
+"HA030191","Stoneham Ln opp Concorde Club N","","50 57.3878N","1 22.3119W","",
+"HA030192","Chestnut Ave opp Barton Peveril Coll W","","50 57.6679N","1 21.9237W","",
+"HA030193","Chestnut Ave os Barton Peveril Coll E","","50 57.6700N","1 21.8997W","",
+"HA030194","Chestnut Ave opp Eastleigh Coll W","","50 57.6425N","1 21.6216W","",
+"HA030195","Chestnut Ave os Eastleigh Coll E","","50 57.6580N","1 21.5846W","",
+"HA030196","Chestnut Ave nr Desborough Rd E","","50 57.6461N","1 21.3891W","",
+"HA030197","Chestnut Ave nr High St W","","50 57.6285N","1 21.3279W","",
+"HA030198","Southampton Rd nr York Rd NE","","50 57.5557N","1 21.3391W","",
+"HA030199","Southampton Rd nr York Rd SW","","50 57.5085N","1 21.3740W","",
+"HA030200","Wide Ln nr Parkway Station NE","","50 57.1627N","1 21.6956W","",
+"HA030201","Parkway Station Wide Ln SW","","50 57.0581N","1 21.8073W","",
+"HA030202","Southampton Rd nr Derby Rd SW","","50 57.7356N","1 21.1820W","",
+"HA030203","Southampton Rd nr Derby Rd NE","","50 57.7502N","1 21.1775W","",
+"HA030204","Southampton Rd nr Campbell Rd N","","50 57.8862N","1 21.0910W","",
+"HA030205","Southampton Rd nr Campbell Rd S","","50 57.8846N","1 21.0851W","",
+"HA030206","Southampton Rd nr The Swan Centre N","","50 58.0532N","1 21.0451W","",
+"HA030207","Eastleigh Station Station Hill S","","50 58.1637N","1 21.0240W","",
+"HA030208","Eastleigh bus station Stnd E","","50 58.1793N","1 21.1203W","",
+"HA030209","Eastleigh bus station Stnd D","","50 58.1885N","1 21.1202W","",
+"HA030212","Eastleigh bus station Stnd A","","50 58.2176N","1 21.1163W","",
+"HA030213","Romsey Rd nr Newtown Rd E","","50 58.2319N","1 21.2580W","",
+"HA030214","Leigh Rd nr Smithe Cl E","","50 58.2010N","1 21.6173W","",
+"HA030215","Leigh Rd nr Sopwith Rd W","","50 58.2017N","1 21.6549W","",
+"HA030216","Leigh Rd nr Dew Ln SE","","50 58.2603N","1 21.9139W","",
+"HA030217","Leigh Rd nr Dew Ln NW","","50 58.2643N","1 21.9429W","",
+"HA030218","Derby Rd nr Passfield Ave W","","50 57.8942N","1 22.1649W","",
+"HA030219","Derby Rd nr Spencer Rd E","","50 57.8906N","1 22.0975W","",
+"HA030220","Derby Rd nr Grantham Rd W","","50 57.8586N","1 21.8570W","",
+"HA030221","Derby Rd nr Grantham Rd E","","50 57.8595N","1 21.8279W","",
+"HA030222","Derby Rd nr Nutbeam Rd W","","50 57.8229N","1 21.5525W","",
+"HA030223","Derby Rd nr Nutbeam Rd E","","50 57.8244N","1 21.5277W","",
+"HA030224","Derby Rd os All Saints Church E","","50 57.8018N","1 21.3340W","",
+"HA030225","Derby Rd nr High St os cafe W","","50 57.7878N","1 21.2573W","",
+"HA030233","Bishopstoke Rd opp Dutton Ln W","","50 58.2056N","1 20.7961W","",
+"HA030234","Bishopstoke Rd nr Chickenhall Ln E","","50 58.2164N","1 20.7011W","",
+"HA030235","Riverside at jnc Fair Oak Rd S","","50 58.1899N","1 20.2058W","",
+"HA030236","Spring Ln opp 16 NE","","50 58.2686N","1 20.2047W","",
+"HA030237","Sedgewick Rd opp 2 NE","","50 58.2630N","1 20.0680W","",
+"HA030238","Sedgewick Rd nr Hamilton Rd SW","","50 58.2770N","1 20.0653W","",
+"HA030239","Sedgewick Rd nr East Dr SW","","50 58.4106N","1 20.0215W","",
+"HA030240","Sedgewick Rd nr West Dr NE","","50 58.4514N","1 19.9961W","",
+"HA030247","Stoke Park Rd os 61 E","","50 58.4854N","1 19.8922W","",
+"HA030248","Stoke Park Rd opp 61 W","","50 58.4828N","1 19.9085W","",
+"HA030249","Underwood Rd os 28 W","","50 58.4220N","1 19.8427W","",
+"HA030250","Underwood Rd os 31 E","","50 58.4235N","1 19.8239W","",
+"HA030251","Underwood Rd East Dr N","","50 58.3492N","1 19.7617W","",
+"HA030252","Underwood Rd East Dr S","","50 58.3346N","1 19.7500W","",
+"HA030253","Underwood Rd nr Shears Rd N","","50 58.1915N","1 19.7366W","",
+"HA030254","Underwood Rd nr Hamilton Rd S","","50 58.1801N","1 19.7265W","",
+"HA030259","Underwood Rd nr Fair Oak Rd NW","","50 58.0029N","1 19.6804W","",
+"HA030260","Fair Oak Rd nr Alan Drayton Way W","","50 57.9770N","1 19.5808W","",
+"HA030261","Fair Oak Rd os 207 SE","","50 57.8931N","1 19.3599W","",
+"HA030262","Fair Oak Rd os Welcome Inn NW","","50 57.8811N","1 19.3327W","",
+"HA030263","Fair Oak Rd nr Weavils Rd NE","","50 57.8917N","1 19.1061W","",
+"HA030264","Fair Oak Rd nr Weavils Rd SW","","50 57.8989N","1 19.0573W","",
+"HA030265","Fair Oak Rd nr Haig Rd NE","","50 57.9373N","1 18.8765W","",
+"HA030266","Fair Oak Rd nr Haig Rd SW","","50 57.9425N","1 18.8533W","",
+"HA030267","Fair Oak Rd nr Sandy Ln SE","","50 57.8633N","1 18.4094W","",
+"HA030268","Fair Oak Rd opp 365 NW","","50 57.8541N","1 18.4035W","",
+"HA030269","Sandy Ln nr New Rd NE","","50 57.9480N","1 18.3141W","",
+"HA030272","Sandy Ln opp Victena Rd N","","50 58.0996N","1 18.2272W","",
+"HA030273","Sandy Ln nr Winchester Rd NE","","50 58.3074N","1 18.1455W","",
+"HA030283","Winchester Rd nr Witt Rd SE","","50 58.1324N","1 17.9379W","",
+"HA030289","Fair Oak Rd opp Cricketers Arms W","","50 57.8731N","1 17.8752W","",
+"HA030292","Fair Oak Rd os 412 W","","50 57.7887N","1 18.2088W","",
+"HA030305","Wildern Ln os Co-Op N","","50 54.8370N","1 18.2418W","",
+"HA030306","St Johns Rd os shops NE","","50 54.7840N","1 18.2272W","",
+"HA030307","St Johns Rd opp church hall SW","","50 54.7447N","1 18.2423W","",
+"HA030308","Lower Northam Rd os Somerfield SW","","50 54.8246N","1 18.1635W","",
+"HA030309","Lower Northam Rd nr Cedar Cl NE","","50 54.8460N","1 18.1222W","",
+"HA030310","Wildern Ln nr Dean Ct NE","","50 54.9667N","1 18.1912W","",
+"HA030311","Wildern Ln opp Wildern School NW","","50 55.0654N","1 18.1804W","",
+"HA030312","Wilden Ln os Shamblehurst School SE","","50 55.1310N","1 18.2374W","",
+"HA030313","Wildern Ln os Hedge End Junior School N","","50 55.1868N","1 18.2741W","",
+"HA030314","Wildern Ln nr Westward Rd S","","50 55.2820N","1 18.2258W","",
+"HA030315","Wildern Ln nr Westward Rd N","","50 55.2794N","1 18.2369W","",
+"HA030323","Grange Rd nr Botleigh Grange SE","","50 55.1836N","1 17.8371W","",
+"HA030326","Grange Rd opp Maypole Retirement Home SE","","50 55.0070N","1 17.5436W","",
+"HA030328","Lwr Northam Rd os 116-118 SW","","50 54.9483N","1 17.5505W","",
+"HA030329","Lower Northam Rd os 70 SW","","50 54.9029N","1 17.8115W","",
+"HA030331","Turnpike Way nr Goodlands Vale NE","","50 54.8790N","1 18.7746W","",
+"HA030336","Turnpike Way opp Berrywood Gdns SE","","50 55.1769N","1 18.5193W","",
+"HA030337","Hedge End Superstores off Tollbar Way","","50 55.2299N","1 18.7276W","",
+"HA030338","Tollbar Way opp McDonalds N","","50 55.4250N","1 18.7802W","",
+"HA030339","Tollbar Way os Pizza Hut S","","50 55.4641N","1 18.7327W","",
+"HA030342","Tollbar Way nr Wellington Park SW","","50 55.5527N","1 18.6477W","",
+"HA030343","Tollbar Way nr Wellington Park NE","","50 55.5699N","1 18.6407W","",
+"HA030344","Tollbar Way nr Wellstead Way N","","50 55.8610N","1 18.5006W","",
+"HA030345","Maunsell Way nr Peppercorn Way W","","50 56.0512N","1 18.2800W","",
+"HA030346","Maunsell Way nr Peppercorn Way E","","50 56.0509N","1 18.2220W","",
+"HA030347","Maunsell Way nr Marlborough Gdns SE","","50 55.9900N","1 18.0641W","",
+"HA030348","Maunsell Way nr Marlborough Gdns NW","","50 55.9868N","1 18.0667W","",
+"HA030349","Maunsell Way nr Martley Gdns NW","","50 55.9116N","1 17.8527W","",
+"HA030350","Maunsell Way nr Martley Gdns SE","","50 55.9154N","1 17.8526W","",
+"HA030351","Hedge End Station","","50 55.9241N","1 17.6800W","",
+"HA030352","Maunsell Way nr Watkin Rd NW","","50 55.8303N","1 17.7045W","",
+"HA030353","Maunsell Way nr Watkin Rd SE","","50 55.8243N","1 17.6900W","",
+"HA030354","Maunsell Way nr Giles Cl SW","","50 55.6392N","1 17.7714W","",
+"HA030355","Maunsell Way nr Giles Cl NE","","50 55.6263N","1 17.7861W","",
+"HA030356","Locke Rd nr Walker Gdns NE","","50 55.3750N","1 17.8915W","",
+"HA030357","Locke Rd nr Missenden Acres SW","","50 55.3523N","1 17.8969W","",
+"HA030377","Moorgreen Rd os 5 N","","50 55.6741N","1 19.6781W","",
+"HA030378","Moorgreen Rd nr Botley Rd S","","50 55.6628N","1 19.6715W","",
+"HA030379","Botley Rd nr Moorgreen Rd E","","50 55.6384N","1 19.6505W","",
+"HA030380","Botley Rd opp Moorgreen Hospital W","","50 55.6308N","1 19.5524W","",
+"HA030381","Botley Rd nr Marshall Dr NW","","50 55.5998N","1 19.2336W","",
+"HA030382","Botley Rd nr Marshall Dr SE","","50 55.5880N","1 19.1501W","",
+"HA030383","High St opp St Brigid ch W","","50 55.6377N","1 19.9109W","",
+"HA030384","High St os St Brigid ch E","","50 55.6447N","1 19.9108W","",
+"HA030385","High St os Netto E","","50 55.6580N","1 20.1607W","",
+"HA030386","High St os 48 W","","50 55.6565N","1 20.1847W","",
+"HA030387","High St nr Barbe Baker Ave E","","50 55.7325N","1 20.5430W","",
+"HA030388","High St nr Barbe Baker Ave W","","50 55.7255N","1 20.5525W","",
+"HA030389","Swaythling Rd nr Barnsland SE","","50 55.9319N","1 20.8049W","",
+"HA030390","Swaythling Rd nr Barnsland NW","","50 55.9558N","1 20.8267W","",
+"HA030391","Swaythling Rd nr Romill Cl SE","","50 56.1037N","1 21.1261W","",
+"HA030395","Bursledon Rd nr Windhover Rbt SE","","50 53.8210N","1 19.3516W","",
+"HA030396","Bursledon Rd nr Windhover Rbt NW","","50 53.8287N","1 19.3796W","",
+"HA030402","Bursledon Rd nr Foord Rd NE","","50 54.2936N","1 18.5144W","",
+"HA030404","Bursledon Rd nr Alexandra Rd NE","","50 54.4397N","1 18.4013W","",
+"HA030405","Bursledon Rd opp 43 NE","","50 54.5882N","1 18.3257W","",
+"HA030407","St Johns Rd nr Newcliffe Gdns NE","","50 54.6227N","1 18.4106W","",
+"HA030408","St Johns Rd nr Newcliffe Gdns SW","","50 54.6249N","1 18.4148W","",
+"HA030410","St Johns Rd nr Foord Rd NE","","50 54.3925N","1 18.7272W","",
+"HA030413","Heathhouse Ln Bursledon Rd NW","","50 54.2513N","1 18.4801W","",
+"HA030414","Heathhouse Ln nr Upper St Helens Rd SE","","50 54.2482N","1 18.4050W","",
+"HA030415","Heathhouse Ln nr Sherwood Ave SE","","50 54.2104N","1 18.2093W","",
+"HA030416","Heathhouse Ln nr Sherwood Ave NW","","50 54.1957N","1 18.1874W","",
+"HA030417","Kings Copse Ave nr Heathhouse Ln NE","","50 54.3072N","1 17.8034W","",
+"HA030418","Kings Copse Ave nr Heathhouse Ln SW","","50 54.3055N","1 17.7855W","",
+"HA030419","Kings Copse Ave nr Duke Rd NE","","50 54.4362N","1 17.5463W","",
+"HA030420","Kings Copse Ave nr Duke Rd SW","","50 54.4453N","1 17.5325W","",
+"HA030421","Kings Copse Ave nr Sovereign Dr NE","","50 54.5804N","1 17.4835W","",
+"HA030422","Kings Copse Ave nr Sovereign Dr SW","","50 54.5896N","1 17.4757W","",
+"HA030423","Kings Copse Ave nr Whitebeam Rd S","","50 54.7728N","1 17.4396W","",
+"HA030424","Kings Copse Ave nr Whitebeam Rd N","","50 54.7922N","1 17.4445W","",
+"HA030425","Kings Copse Ave nr Broad Oak N","","50 54.9094N","1 17.4512W","",
+"HA030426","Kings Copse Ave nr Broad Oak S","","50 54.9255N","1 17.4501W","",
+"HA030431","Winchester St nr Woodhouse Ln NW","","50 55.4140N","1 16.6821W","",
+"HA030435","Holmesland Ln nr Holmesland Dr N","","50 54.9965N","1 16.7081W","",
+"HA030436","High St nr Mortimer Rd SE","","50 54.9033N","1 16.4697W","",
+"HA030437","High St nr Mortimer Rd NW","","50 54.9001N","1 16.4766W","",
+"HA030438","High St os 25 W","","50 54.8564N","1 16.2981W","",
+"HA030439","High St os 22 E","","50 54.8627N","1 16.2715W","",
+"HA030440","Winchester St nr Holmesland Dr SE","","50 55.1472N","1 16.4625W","",
+"HA030441","High St nr Holmesland Ln SE","","50 54.9735N","1 16.7341W","",
+"HA030442","High St nr Holmesland Ln NW","","50 54.9725N","1 16.7503W","",
+"HA030443","Broad Oak os Broadway Farm E","","50 54.9486N","1 16.9906W","",
+"HA030444","Broad Oak opp Broadway Farm W","","50 54.9532N","1 17.0349W","",
+"HA030445","Grange Rd nr footpath to Marls Rd W","","50 54.9727N","1 17.3896W","",
+"HA030446","West end Rd opp 273 SW","","50 55.3791N","1 20.6428W","",
+"HA030447","West end Rd os 277 NE","","50 55.3870N","1 20.6179W","",
+"HA030450","Townhill Way nr Swaythling Rd NE","","50 56.0284N","1 20.9709W","",
+"HA030451","Townhill Way nr Swaythling Rd SW","","50 56.0133N","1 20.9694W","",
+"HA030452","Townhill Way nr Frome Rd NE","","50 55.9906N","1 21.1703W","",
+"HA030453","Townhill Way os Two Brothers ph SW","","50 55.9525N","1 21.1948W","",
+"HA030454","Townhill Way nr path to Gatcombe Gdns N","","50 55.8309N","1 21.2588W","",
+"HA030456","Townhill Way nr Cerne Cl SW","","50 55.6129N","1 21.1722W","",
+"HA030457","Townhill Way nr Cerne Cl NE","","50 55.6007N","1 21.1988W","",
+"HA030465","Burnetts Ln os Chalcroft Pk NE","","50 56.4838N","1 18.3453W","",
+"HA030466","Burnetts Ln opp Chalcroft Pk SW","","50 56.4827N","1 18.3428W","",
+"HA030477","Oakhill opp Crows Nest ph NW","","50 53.3853N","1 18.5561W","",
+"HA030478","Oakhill os Crows Nest ph SE","","50 53.3922N","1 18.5414W","",
+"HA030483","Portsmouth Rd opp One Stop NE","","50 53.3785N","1 18.9622W","",
+"HA030484","Portsmouth Rd opp community cnt SW","","50 53.3706N","1 19.0067W","",
+"HA030485","Jurd Way nr Lionheart Way S","","50 53.4000N","1 19.3279W","",
+"HA030486","Jurd Way nr Lionheart Way N","","50 53.4351N","1 19.3239W","",
+"HA030487","Windhover Tesco access rd","","50 53.6219N","1 19.2521W","",
+"HA030488","Hamble Ln os Tesco SW","","50 53.6948N","1 19.2630W","",
+"HA030490","Portsmouth Rd nr Beverley Gdns NW","","50 53.3538N","1 19.7414W","",
+"HA030491","Portsmouth Rd os Plough ph NW","","50 53.3644N","1 19.8001W","",
+"HA030492","Portsmouth Rd nr Grange Rd SE","","50 53.4494N","1 20.1205W","",
+"HA030493","Portsmouth Rd nr Grange Rd NW","","50 53.4500N","1 20.1358W","",
+"HA030494","Portsmouth Rd opp sports ground NW","","50 53.5113N","1 20.3824W","",
+"HA030495","Portsmouth Rd os sports ground SE","","50 53.5178N","1 20.3908W","",
+"HA030496","Hamble Ln nr Pound Rd NE","","50 53.2863N","1 19.4421W","",
+"HA030498","Hamble Ln nr Cunningham Gdns N","","50 53.1655N","1 19.4541W","",
+"HA030500","Hamble Ln opp Broadway N","","50 52.4137N","1 19.7097W","",
+"HA030501","Hamble Ln nr Broadway S","","50 52.3975N","1 19.6980W","",
+"HA030502","Hamble Ln opp 106 N","","50 52.0730N","1 19.6617W","",
+"HA030504","Hamble Ln nr Verdon Ave NE","","50 51.8379N","1 19.6933W","",
+"HA030505","Hamble Ln nr Verdon Ave SW","","50 51.8288N","1 19.6942W","",
+"HA030506","Hamble Ln opp 42 NW","","50 51.6904N","1 19.6468W","",
+"HA030507","Hamble Ln os 34 SE","","50 51.6772N","1 19.6129W","",
+"HA030508","Hamble Ln nr Ensign Way NW","","50 51.5634N","1 19.4227W","",
+"HA030509","Hamble Ln opp Fire Stn SE","","50 51.5471N","1 19.3215W","",
+"HA030510","Hamble Ln nr Copse Ln NW","","50 51.5305N","1 19.2433W","",
+"HA030511","High St os village hall NE","","50 51.5323N","1 19.1777W","",
+"HA030512","Hamble Square","","50 51.5458N","1 18.9038W","",
+"HA030516","Hound Way nr Hamble Ln E","","50 52.5875N","1 19.7985W","",
+"HA030517","Hound Way nr Hamble Ln W","","50 52.5882N","1 19.8266W","",
+"HA030518","Hound Way nr Hound Rd W","","50 52.5869N","1 20.0790W","",
+"HA030519","Hound Way nr Hound Rd E","","50 52.5897N","1 20.0969W","",
+"HA030521","Woolston Rd os Hound Post Office NW","","50 52.7047N","1 20.3093W","",
+"HA030522","Woolston Rd os 64 SE","","50 52.7318N","1 20.3294W","",
+"HA030523","Woolston Rd nr Ingleside W","","50 52.9410N","1 20.5823W","",
+"HA030524","Grange Rd nr Woolston Rd NE","","50 52.9449N","1 20.7025W","",
+"HA030525","Grange Rd nr Woolston Rd SW","","50 52.9374N","1 20.7086W","",
+"HA030526","Grange Rd os Mill House ph SW","","50 52.8437N","1 20.9377W","",
+"HA030527","Grange Rd opp Mill House ph NE","","50 52.8330N","1 20.9549W","",
+"HA030528","Grange Rd nr St Edwards Rd NE","","50 52.7840N","1 21.0749W","",
+"HA030529","Grange Rd nr St Edwards Rd SW","","50 52.7578N","1 21.1197W","",
+"HA030530","Grange Rd nr New Rd SW","","50 52.6387N","1 21.3294W","",
+"HA030531","Grange Rd nr New Rd NE","","50 52.6366N","1 21.3448W","",
+"HA030532","Victoria Rd opp York Rd SE","","50 52.5004N","1 21.3049W","",
+"HA030533","Victoria Rd nr Manchester Rd NW","","50 52.4728N","1 21.2856W","",
+"HA030534","Station Rd opp Lloyds Bank NE","","50 52.3938N","1 21.1426W","",
+"HA030535","Station Rd opp social club SW","","50 52.4162N","1 21.1022W","",
+"HA030536","Station Rd nr Denzil Ave E","","50 52.4747N","1 20.9445W","",
+"HA030537","Station Rd opp Denzil Ave NW","","50 52.4495N","1 20.8783W","",
+"HA030538","St Marys Rd nr Station Rd SW","","50 52.4697N","1 20.6325W","",
+"HA030539","St Marys Rd nr Station Rd NE","","50 52.4923N","1 20.6185W","",
+"HA030540","Ingleside nr Yaverland S","","50 52.7007N","1 20.5533W","",
+"HA030541","Ingleside nr Yaverland N","","50 52.7040N","1 20.5584W","",
+"HA030542","Ingleside nr Bowcombe NW","","50 52.8536N","1 20.5819W","",
+"HA030546","Winchester Rd nr Oatlands Rd SE","","50 55.5303N","1 16.7349W","",
+"HA030548","Winchester Rd nr Madoxford Ln SE","","50 55.7254N","1 16.8659W","",
+"HA030564","Botley Rd opp Holiday Inn E","","50 55.6309N","1 19.3902W","",
+"HA040001","Bridge Rd opp Spinnaker ph NW","","50 53.0220N","1 17.9891W","",
+"HA040002","Bridge Rd opp Swanwick Shore Rd SE","","50 52.9386N","1 17.8402W","",
+"HA040005","Bridge Rd nr Chapel Rd NW","","50 52.5871N","1 17.3551W","",
+"HA040006","Bridge Rd nr Chapel Rd SE","","50 52.5775N","1 17.2922W","",
+"HA040014","A27 Bridge Road opp 39 SE","","50 52.3007N","1 16.0710W","",
+"HA040023","Centre Way os community centre E","","50 51.7933N","1 16.3783W","",
+"HA040024","Locks Rd nr Church Rd S","","50 51.7547N","1 16.2442W","",
+"HA040043","Osborne Rd nr Romford Rd W","","50 50.8968N","1 17.7321W","",
+"HA040047","Warsash Rd opp Ferryman ph E","","50 51.2003N","1 17.9645W","",
+"HA040048","Brook Ln nr Warsash Rd N","","50 51.2232N","1 18.0076W","",
+"HA040075","Hunts Pond Rd nr Lower Church Rd SW","","50 51.7096N","1 15.6020W","",
+"HA040076","Church Rd nr Hunts Pond Rd SE","","50 51.6898N","1 15.6245W","",
+"HA040078","Hunts Pond Rd nr Church Rd NW","","50 51.6545N","1 15.5799W","",
+"HA040082","Abshot Rd nr Talland Rd NE","","50 51.1933N","1 15.8574W","",
+"HA040083","Abshot Rd nr Talland Rd SW","","50 51.1809N","1 15.8653W","",
+"HA040108","Southampton Hill nr High St NW","","50 51.0295N","1 14.1425W","",
+"HA040109","Southampton Hill nr High St SE","","50 51.0356N","1 14.1552W","",
+"HA040240","Fareham bus station Stnd A","","50 51.1163N","1 10.7759W","",
+"HA040276","The Avenue opp Fareham Coll E","","50 51.1262N","1 11.9716W","",
+"HA040277","The Avenue nr Bishopsfield Rd W","","50 51.1043N","1 12.0828W","",
+"HA040297","Stubbington Ln nr Eric Rd S","","50 49.3016N","1 12.8879W","",
+"HA040298","Stubbington Ln nr William Cl NW","","50 49.1651N","1 12.8084W","",
+"HA040471","Hunts Pond Rd nr Admirals Rd SE","","50 52.1849N","1 15.8545W","",
+"HA050111","Marine Parade East nr Milvil Rd NW","","50 48.1129N","1 12.2394W","",
+"HA050112","Milvil Rd nr Marine Parade East SW","","50 48.1496N","1 12.2371W","",
+"HA050135","Gomer Ln opp Bay House School NE","","50 47.2736N","1 9.9580W","",
+"HA050136","Gomer Ln os Bay House School SW","","50 47.2823N","1 9.9025W","",
+"HA050159","Bury Rd os Hospital SE","","50 47.5570N","1 8.8659W","",
+"HA050160","Bury Rd opp Hospital NW","","50 47.5489N","1 8.8575W","",
+"HA050182","Gosport Bus Stn stand A","","50 47.6709N","1 7.0564W","",
+"HA080007","Romsey Rd nr A36 Salisbury Rd NE","","50 57.1599N","1 32.1672W","",
+"HA080008","Romsey Rd nr A36 Salisbury Rd SW","","50 57.1243N","1 32.1803W","",
+"HA080019","Salisbury Rd nr Testwood Cres NW","","50 55.9253N","1 30.4309W","",
+"HA080020","Salisbury Rd nr Testwood Cres SE","","50 55.8865N","1 30.3272W","",
+"HA080021","Salisbury Rd nr Stanley Rd NW","","50 55.7676N","1 30.1508W","",
+"HA080022","Salisbury Rd nr Stanley Rd SE","","50 55.7443N","1 30.1110W","",
+"HA080023","Salisbury Rd nr Sylvia Cres SE","","50 55.6500N","1 30.0292W","",
+"HA080024","Salisbury Rd nr Sylvia Cres NW","","50 55.5938N","1 30.0033W","",
+"HA080025","Salisbury Rd nr Hammonds Ln NW","","50 55.4138N","1 29.8055W","",
+"HA080026","Salisbury Rd nr Testwood Ln SE","","50 55.3681N","1 29.7121W","",
+"HA080027","Salisbury Rd nr Oakmount Ave NW","","50 55.2601N","1 29.5733W","",
+"HA080028","Salisbury Rd nr Stannington Cres SE","","50 55.2118N","1 29.4936W","",
+"HA080029","Salisbury Rd nr Water Ln NW","","50 55.1885N","1 29.4673W","",
+"HA080030","Library Rd nr Testwood Ln E","","50 55.1367N","1 29.2357W","",
+"HA080031","Commercial Rd opp RC Church NW","","50 55.1126N","1 29.1549W","",
+"HA080032","Commercial Rd opp Red Lion ph W","","50 55.0957N","1 28.9835W","",
+"HA080033","Commercial Rd nr bypass jnc NE","","50 55.1299N","1 28.9226W","",
+"HA080034","Ringwood Rd os Asda SW","","50 55.0981N","1 29.4120W","",
+"HA080043","Water Ln opp Totton Coll SW","","50 55.2235N","1 30.4631W","",
+"HA080044","Water Ln os Totton Coll NE","","50 55.2198N","1 30.4794W","",
+"HA080049","Calmore Rd nr Shepherds Hey Rd S","","50 55.6314N","1 31.2485W","",
+"HA080051","Calmore Rd nr Shepherds Hey Rd N","","50 55.7385N","1 31.1885W","",
+"HA080052","Calmore Rd nr The Drove NE","","50 55.7412N","1 31.1918W","",
+"HA080054","Calmore Rd nr Cooks Ln S","","50 55.8963N","1 31.1091W","",
+"HA080056","Calmore Dr nr Embley Cl S","","50 55.8709N","1 30.5792W","",
+"HA080057","Blackwater Dr nr Bearslane Cl SE","","50 55.6830N","1 30.5445W","",
+"HA080058","Blackwater Dr nr Mortimer Cl S","","50 55.5333N","1 30.3702W","",
+"HA080059","Blackwater Dr nr Calmore Dr NW","","50 55.5154N","1 30.6094W","",
+"HA080060","Calmore Dr nr Bowater Way SW","","50 55.5185N","1 30.6862W","",
+"HA080061","Calmore Dr nr Appletree Cl NW","","50 55.4656N","1 30.9377W","",
+"HA080063","Calmore Dr nr Richmond Cl NE","","50 55.6797N","1 31.0516W","",
+"HA080064","Calmore Dr nr Friars Croft NE","","50 55.8319N","1 30.9322W","",
+"HA080065","Calmore Dr nr Warren Pl NE","","50 55.9091N","1 30.8187W","",
+"HA080068","Loperwood opp Tachbury Mount Hosp E","","50 55.9296N","1 31.8738W","",
+"HA080069","Loperwood os Tachbury Mount Hosp W","","50 55.9269N","1 31.8806W","",
+"HA080074","Winsor Rd opp Compass Inn NE","","50 55.6841N","1 32.9588W","",
+"HA080075","Winsor Rd nr Compass Inn SW","","50 55.6766N","1 32.9708W","",
+"HA080090","Romsey Rd A31 nr Southampton Rd A336 SW","","50 55.3804N","1 34.7185W","",
+"HA080091","Romsey Rd A31 nr Southampton Rd A336 NE","","50 55.3440N","1 34.7914W","",
+"HA080092","Southampton Rd A336 nr Romsey Rd A36 E","","50 55.2214N","1 34.7797W","",
+"HA080093","Southampton Rd A336 nr Romsey Rd A36 W","","50 55.2145N","1 34.8028W","",
+"HA080094","Southampton Rd A336 nr Fir Tree Rd SE","","50 55.1532N","1 34.4201W","",
+"HA080095","Southampton Rd A336 nr Fir Tree Rd NW","","50 55.1484N","1 34.4227W","",
+"HA080096","Southampton Rd A336 nr Barneyhayes Ln E","","50 55.1330N","1 34.2001W","",
+"HA080097","Southampton Rd A336 nr Barneyhayes Ln W","","50 55.1292N","1 34.2001W","",
+"HA080098","Southampton Rd A336 nr Winsor Rd SE","","50 55.0366N","1 33.8015W","",
+"HA080099","Southampton Rd A336 nr Winsor Rd NW","","50 55.0354N","1 33.7716W","",
+"HA080100","Ringwood Rd A336 nr Woodlands Rd W","","50 54.9311N","1 31.7866W","",
+"HA080101","Ringwood Rd A336 nr Woodlands Rd E","","50 54.9265N","1 31.7107W","",
+"HA080102","Ringwood Rd A336 nr A326 SE","","50 54.9054N","1 31.3012W","",
+"HA080103","Ringwood Rd A336 nr A326 NW","","50 54.8956N","1 31.2885W","",
+"HA080104","Ringwood Rd A336 nr Crabbs Way NE","","50 54.9276N","1 31.0697W","",
+"HA080105","Ringwood Rd A336 nr Crabbs Way SW","","50 54.9265N","1 31.0526W","",
+"HA080107","Ringwood Rd A336 nr Ln rchwood Rd SW","","50 54.9948N","1 30.6089W","",
+"HA080108","Ringwood Rd A336 nr Ln rchwood Rd NE","","50 55.0080N","1 30.5473W","",
+"HA080109","Ringwood Rd A336 nr Testbourne Ave SW","","50 55.0420N","1 30.2994W","",
+"HA080111","Ringwood Rd A336 nr Calmore Rd E","","50 55.0583N","1 30.1926W","",
+"HA080112","Ringwood Rd A336 nr Southern Gdns E","","50 55.0528N","1 29.9212W","",
+"HA080113","Ringwood Rd nr Bagber Rd E","","50 55.0362N","1 29.6969W","",
+"HA080115","Woodlands Rd os White Horse SW","","50 54.9094N","1 31.7492W","",
+"HA080120","Woodlands Rd nr Green Cl NE","","50 54.3228N","1 32.3994W","",
+"HA080121","Woodlands Rd nr Green Cl SW","","50 54.3109N","1 32.4098W","",
+"HA080134","Bourne Rd - nr Paradise Ln N","","50 54.7241N","1 33.2045W","",
+"HA080135","Bourne Rd - nr Paradise Ln S","","50 54.7235N","1 33.2002W","",
+"HA080200","A35 Totton bypass nr Rushington Rbt SW","","50 54.8024N","1 29.4127W","",
+"HA080201","A35 Totton bypass nr Rushington Rbt NE","","50 54.8207N","1 29.4048W","",
+"HA080203","Spicers Hill nr Hounsdown Ave S","","50 54.5668N","1 29.7071W","",
+"HA080211","A35 Main Rd adj New Inn SW","","50 54.3964N","1 29.8532W","",
+"HA080212","A35 Main Rd opp New Inn NE","","50 54.4051N","1 29.8702W","",
+"HA080221","Lyndhurst Rd os 159 SW","","50 53.5630N","1 31.3022W","",
+"HA080222","Lyndhurst Rd os 124 NE","","50 53.5668N","1 31.3149W","",
+"HA080225","Ashdene Rd nr Whartons Ln SW","","50 54.1005N","1 30.8188W","",
+"HA080226","Ashdene Rd nr Whartons Ln NE","","50 54.1032N","1 30.8205W","",
+"HA080236","Lackford Ave os 108 NE","","50 54.7929N","1 29.8353W","",
+"HA080237","Lackford Ave os 87 SW","","50 54.7908N","1 29.8319W","",
+"HA080254","Tavells Ln opp Woodpecker Dr NE","","50 53.5396N","1 27.4610W","",
+"HA080255","Tavells Ln nr Woodpecker Dr SW","","50 53.5305N","1 27.4748W","",
+"HA080260","Main Rd nr Vicarage Rd NE","","50 53.4080N","1 27.1222W","",
+"HA080261","Main Rd opp ch SW","","50 53.3878N","1 27.1864W","",
+"HA080287","Claypits Ln opp Rowhill Dr NW","","50 51.8677N","1 25.8895W","",
+"HA080288","Claypits Ln nr Rowhill Dr SE","","50 51.8605N","1 25.8614W","",
+"HA080294","Cumberland Way nr Capella Gdns SW","","50 51.8717N","1 25.2772W","",
+"HA080295","Challenger Way nr Corsair Dr SW","","50 51.8519N","1 25.1948W","",
+"HA080312","Claypits Ln nr Draper Copse SW","","50 52.0687N","1 25.4087W","",
+"HA080313","Claypits Ln nr Draper Copse NE","","50 52.0746N","1 25.3984W","",
+"HA080327","Beaulieu Rd os Hythe Hospital NE","","50 51.5495N","1 24.1934W","",
+"HA080328","Beaulieu Rd opp Fairview Parade SW","","50 51.5361N","1 24.2115W","",
+"HA080335","Beaulieu Rd os The Heath ph SW","","50 51.1048N","1 25.0275W","",
+"HA080336","Beaulieu Rd nr Mansell Cl NE","","50 51.0887N","1 25.0414W","",
+"HA080357","Prospect Pl os Ferry Terminal SE","","50 52.2422N","1 23.9748W","",
+"HA080431","Fawley Rd nr Cedar Rd N","","50 50.8587N","1 23.6380W","",
+"HA080432","Fawley Rd nr Hardley Ln track S","","50 50.8246N","1 23.6163W","",
+"HA080435","Long Ln nr Main Rd NW","","50 50.3850N","1 23.3365W","",
+"HA080436","Long Ln nr Main Rd SE","","50 50.3817N","1 23.3220W","",
+"HA080446","Foxcroft Dr nr Studley Ave N","","50 49.7041N","1 23.5388W","",
+"HA080447","Foxcroft Dr nr Great Elms Cl S","","50 49.6133N","1 23.5153W","",
+"HA080457","Hampton Ln nr Rollestone Rd S","","50 49.4040N","1 22.5026W","",
+"HA080458","Hampton Ln nr Rollestone Rd N","","50 49.3971N","1 22.5129W","",
+"HA080461","Hampton Ln nr Blackfield Rd SE","","50 49.1011N","1 22.3704W","",
+"HA080463","Blackfield Rd nr Hampton Ln NE","","50 49.1170N","1 22.3088W","",
+"HA080466","Foresters Rd nr Blackfield Ln SE","","50 49.2670N","1 22.1109W","",
+"HA080467","Foresters Rd nr Blackfield Ln NW","","50 49.2621N","1 22.1101W","",
+"HA080476","School Rd nr The Square NE","","50 49.6112N","1 21.0337W","",
+"HA080487","B3053 Calshot Beach E","","50 48.5782N","1 19.1805W","",
+"HA080527","High St os Lyndhurst Park Hotel E","","50 52.3406N","1 34.2898W","",
+"HA080528","High St opp Lyndhurst Park Hotel W","","50 52.3332N","1 34.3103W","",
+"HA080531","High St opp ch E","","50 52.3577N","1 34.6802W","",
+"HA080541","Lyndhurst Rd opp Brockenhurst College N","","50 49.3391N","1 34.3121W","",
+"HA080544","Brookley Rd opp rear Forresters Arms NW","","50 49.0933N","1 34.3680W","",
+"HA080545","Brookley Rd os front Forresters Arms NE","","50 49.0975N","1 34.3382W","",
+"HA080562","Southamtpon Rd A337 opp Hobbler Inn SE","","50 47.4203N","1 33.9713W","",
+"HA080563","Southamtpon Rd A337 os Hobbler Inn SE","","50 47.4213N","1 33.9679W","",
+"HA080661","Lymington bus station stand C","","50 45.4822N","1 32.4350W","",
+"HA081080","Lepe Rd os Whitefield Farm SE","","50 48.2041N","1 21.9175W","",
+"HA081165","Ringwood Rd nr Tachbury Ln E","","50 54.9989N","1 32.1529W","",
+"HA081166","Ringwood Rd nr Tachbury Ln W","","50 54.9822N","1 32.1454W","",
+"HA100009","Knightwood Rd nr Pilgrims Cl SW","","50 58.7492N","1 24.1670W","",
+"HA100010","Knightwood Rd nr Chidden Holt NE","","50 58.7834N","1 24.1033W","",
+"HA100026","Hool Rd opp Potters Heron S","","51 0.4099N","1 24.7982W","",
+"HA100152","A36 Salisbury Rd nr Lower Common Rd SW","","50 58.1106N","1 35.0347W","",
+"HA100153","Canada Rd nr Salisbury Rd A36 SW","","50 58.1173N","1 35.1218W","",
+"HA100158","A36 Salisbury Rd nr Purley Way SE","","50 58.3542N","1 36.2083W","",
+"HA100159","A36 Salisbury Rd nr Purley Way NW","","50 58.3576N","1 36.2604W","",
+"HA100220","Romsey bus station Stnd A","","50 59.3000N","1 29.8908W","",
+"HA100239","Botley Rd nr Montfort Rd NW","","50 59.1593N","1 27.9639W","",
+"HA100240","Botley Rd nr Highwood Ln SE","","50 59.1541N","1 27.8990W","",
+"HA100762","Rownhams Rd nr Botley Rd SW","","50 58.6528N","1 26.2716W","",
+"HA100763","Botley Rd nr Castle Ln SE","","50 58.6170N","1 26.1233W","",
+"HA100770","Chilworth Rd os Chilworth Arms NW","","50 57.8691N","1 25.0062W","",
+"HA100771","Chilworth Rd opp Chilworth Arms SE","","50 57.8689N","1 24.9712W","",
+"HA100778","Bournemouth Rd nr Chilworth Rd SW","","50 57.4095N","1 24.0603W","",
+"HA100779","Bournemouth Rd nr Chilworth Rd NE","","50 57.3778N","1 24.1034W","",
+"HA100780","Hilton Hotel A27 nr Chilworth Rbt S","","50 57.2437N","1 24.1487W","",
+"HA100783","Fleming Ave nr Bracken Rd E","","50 58.4163N","1 26.3488W","",
+"HA100784","Fleming Ave nr Bracken Rd W","","50 58.4105N","1 26.3762W","",
+"HA100793","Rownhams Ln M27 bridge SW","","50 57.4282N","1 27.1176W","",
+"HA100794","Rownhams Ln M27 bridge NE","","50 57.4288N","1 27.1227W","",
+"HA100795","Rownhams Ln nr Routs Way S","","50 57.1877N","1 27.1400W","",
+"HA100796","Rownhams Ln nr Routs Way N","","50 57.1915N","1 27.1477W","",
+"HA100797","Horns Drove nr Routs Way S","","50 57.2379N","1 27.2496W","",
+"HA100798","Horns Drove nr Routs Way N","","50 57.2152N","1 27.2576W","",
+"HA100804","Romsey Rd nr Upton Cres SE","","50 57.1080N","1 28.0942W","",
+"HA100805","Romsey Rd nr Horns Hill Cl NW","","50 56.8704N","1 27.8270W","",
+"HA100806","Romsey Rd nr Horns Hill Cl SE","","50 56.8628N","1 27.8126W","",
+"HA100807","Romsey Rd nr Nursling St SE","","50 56.7121N","1 27.6700W","",
+"HA100808","Romsey Rd nr Nursling St NW","","50 56.7051N","1 27.6735W","",
+"HA110038","Otterbourne Rd nr Badger Farm Rd S","","51 2.2271N","1 19.6870W","",
+"HA110040","St Cross Rd nr Grange Rd SW","","51 2.6754N","1 19.4922W","",
+"HA110041","St Cross Rd nr Grange Rd NE","","51 2.7067N","1 19.4883W","",
+"HA110042","St Cross Rd nr Mead Rd SW","","51 2.9042N","1 19.3955W","",
+"HA110043","St Cross Rd nr Mead Rd NE","","51 2.9349N","1 19.3934W","",
+"HA110044","St Cross Rd nr Barnes Cl NE","","51 3.0689N","1 19.3392W","",
+"HA110045","St Cross Rd nr Kingsgate Rd SW","","51 3.1453N","1 19.2885W","",
+"HA110046","St Cross Rd nr Ranelagh Rd NE","","51 3.2885N","1 19.2393W","",
+"HA110047","St Cross Rd nr Ranelagh Rd SW","","51 3.3304N","1 19.2138W","",
+"HA110048","St Cross Rd nr Romans Rd SW","","51 3.4359N","1 19.1686W","",
+"HA110049","St Cross Rd nr Romans Rd NE","","51 3.4494N","1 19.1701W","",
+"HA110051","Southgate St nr Archery Ln SW","","51 3.6824N","1 19.0674W","",
+"HA110058","Winchester bus station Stnd F","","51 3.7149N","1 18.6200W","",
+"HA110067","St Georges St nr Upper Brook St NW","","51 3.7573N","1 18.7735W","",
+"HA110108","Winchester Station Stnd C NW","","51 4.0239N","1 19.1489W","",
+"HA110112","Jewry St nr High St SW","","51 3.7850N","1 18.9811W","",
+"HA110125","Romsey Rd os RHC Hosp SW","","51 3.7269N","1 19.7603W","",
+"HA110126","Romsey Rd opp RHC Hosp NE","","51 3.7329N","1 19.7773W","",
+"HA110245","Hursley Rd B3043 nr Ln dwell N","","51 0.8332N","1 23.4919W","",
+"HA110247","Hursley Rd B3043 nr A3090 N","","51 1.0032N","1 23.4914W","",
+"HA110251","A3090 os Hursley PO S","","51 1.5154N","1 23.4265W","",
+"HA110252","A3090 os Hursley ch hall NW","","51 1.5469N","1 23.4654W","",
+"HA110418","Otterbourne Rd nr Compton St S","","51 1.6882N","1 19.8984W","",
+"HA110419","Otterbourne Rd nr Compton St N","","51 1.6781N","1 19.9182W","",
+"HA110420","Otterbourne Rd nr Shawford Rd NE","","51 1.4353N","1 19.9260W","",
+"HA110421","Otterbourne Rd nr Shawford Rd SW","","51 1.4294N","1 19.9209W","",
+"HA110422","Otterbourne Rd nr South Down Rd SW","","51 1.2200N","1 20.1147W","",
+"HA110423","Otterbourne Rd nr South Down Rd NE","","51 1.1547N","1 20.1943W","",
+"HA110424","Otterbourne Rd nr Highways Rd NE","","51 0.9563N","1 20.3169W","",
+"HA110425","Otterbourne Rd nr Highways Rd SW","","51 0.9046N","1 20.3390W","",
+"HA110426","Otterbourne Rd nr Sparrowgrove SW","","51 0.7105N","1 20.4615W","",
+"HA110427","Otterbourne Rd nr Sparrowgrove NE","","51 0.7272N","1 20.4647W","",
+"HA110428","Otterbourne Rd nr Poles Ln NE","","51 0.6068N","1 20.5383W","",
+"HA110429","Otterbourne Rd nr Oakwood Ave SW","","51 0.5287N","1 20.5607W","",
+"HA110430","Main Rd nr Cranbourne Dr NE","","51 0.2837N","1 20.8524W","",
+"HA110431","Main Rd nr Cranbourne Dr SW","","51 0.2386N","1 20.8898W","",
+"HA110432","Otterbourne Hill nr Boyatt Ln SW","","50 59.9451N","1 21.2847W","",
+"HA110433","Otterbourne Hill nr Boyatt Ln NE","","50 59.9452N","1 21.3026W","",
+"HA110549","Durley St nr Manor Rd NE","","50 57.3963N","1 15.0393W","",
+"HA110550","Durley St nr Manor Rd SW","","50 57.3930N","1 15.0342W","",
+"HA110571","Station Hill opp Railway ph NE","","50 54.9527N","1 15.5557W","",
+"HA110572","Station Hill os Railway ph SW","","50 54.9408N","1 15.5567W","",
+"HA110611","St Georges Square NE","","50 57.2133N","1 12.8153W","",
+"HA110817","Snakemoor Ln nr Winchester Rd NE","","50 56.5788N","1 17.5480W","",
+"HA110818","Snakemoor Ln nr Winchester Rd SW","","50 56.5724N","1 17.5549W","",
+"HA120018","Bakers Drove nr Rownhams Ln NE","","50 56.9245N","1 27.1534W","",
+"HA120154","Portswood Rd opp 743 SW","","50 56.1476N","1 22.8521W","",
+"HA120303","St Denys Rd opp 24 NW","","50 55.5106N","1 23.2985W","",
+"HA120304","St Denys Rd opp Stanley Rd SE","","50 55.4909N","1 22.9419W","",
+"HA120305","St Denys Rd os ch NW","","50 55.4932N","1 22.9777W","",
+"HA120306","Cobden Bridge nr Priory Rd E","","50 55.4714N","1 22.8252W","",
+"HA120307","Cobden Bridge nr Priory Rd W","","50 55.4660N","1 22.8312W","",
+"HA120322","Meggeson Ave os 166-186 SE","","50 55.7194N","1 21.3952W","",
+"HA120323","Meggeson Ave opp 17 SE","","50 55.6018N","1 21.3030W","",
+"HA120324","Meggeson Ave os path to Roundhill Cl NW","","50 55.5855N","1 21.2904W","",
+"HA120416","Bitterne Rd West opp 18 NE","","50 55.0455N","1 23.0058W","",
+"HA120417","Bitterne Rd West nr Quayside Rd SW","","50 55.0047N","1 23.0277W","",
+"HA120418","Bitterne Rd West os 88 W","","50 55.0748N","1 22.8168W","",
+"HA120419","Bitterne Rd West os 115 E","","50 55.0858N","1 22.7586W","",
+"HA120420","Bitterne Rd West os 170 W","","50 55.0582N","1 22.5524W","",
+"HA120462","Beauworth Ave os 1 SE","","50 55.3711N","1 20.5643W","",
+"HA120464","Minstead Ave opp Fritham Rd NW","","50 55.2567N","1 20.3799W","",
+"HA120465","Cheriton Ave opp Bramdean Rd NE","","50 55.1544N","1 20.1210W","",
+"HA120466","Minstead Ave os Hare and Hounds ph SE","","50 55.1814N","1 20.1266W","",
+"HA120481","Millbrook Rd West jnc Waterhouse Ln SE","","50 54.7702N","1 26.1724W","",
+"HA120482","Millbrook Rd opp Station SE","","50 54.7181N","1 25.9973W","",
+"HA120483","Millbrook Rd West os Station NW","","50 54.7048N","1 26.0375W","",
+"HA120546","Town Quay opp Red Funnel NE","","50 53.7708N","1 24.2973W","",
+"HA120610","Hinkler Rd opp Kanes Hill Sch NW","","50 54.7336N","1 19.7531W","",
+"HA120611","Hinkler Rd os Kanes Hill Sch SE","","50 54.7275N","1 19.7310W","",
+"HA120612","Hinkler Rd nr Holcroft Rd S","","50 54.5523N","1 19.6619W","",
+"HA120613","Hinkler Rd nr Holcroft Rd N","","50 54.5599N","1 19.6660W","",
+"HA120621","Briton St os City Court E","","50 53.8763N","1 24.1330W","",
+"HA120625","High St os For Your Eyes Only N","","50 54.0036N","1 24.2380W","",
+"HA120626","High St os Ferryman and Firkin S","","50 53.9992N","1 24.2244W","",
+"HA120630","Briton St os Coopers Ct W","","50 53.8853N","1 24.1994W","",
+"HA120633","Orchard Pl os Bowling Green House NE","","50 53.8291N","1 24.0884W","",
+"HA120638","Queens Ter nr Seamen Mission E","","50 53.8707N","1 23.9863W","",
+"HA120641","Canute Rd opp Canute Chambers E","","50 53.8219N","1 23.6380W","",
+"HA120642","Canute Rd os Canute Chambers W","","50 53.8160N","1 23.6475W","",
+"HA120720","Archery Rd opp park NW","","50 53.4728N","1 22.5113W","",
+"HA120721","Archery Rd opp 15 SE","","50 53.4891N","1 22.5239W","",
+"HA120746","Weston Ln os 1 SW","","50 53.2812N","1 22.2947W","",
+"HA120767","Redbridge Ln os Hillyfields Flats NE","","50 56.2501N","1 27.9734W","",
+"HA120776","Hinkler Rd os 2 N","","50 54.8772N","1 19.8646W","",
+"HA120777","Hinkler Rd os 7B S","","50 54.8577N","1 19.8529W","",
+"HA120786","Townhill Way nr Culvery Gdns SE","","50 55.7599N","1 21.1992W","",
+"HA120794","Mansbridge Rd nr White Swan ph NE","","50 56.2720N","1 21.6054W","",
+"HA120796","Swaythling Rd nr Romill Cl NW","","50 56.0999N","1 21.1321W","",
+"HA121017","A33 at Chilworth rbt N","","50 57.1299N","1 24.2655W","",
+"HA121024","Millbrook Rd West os Texaco fill stn W","","50 54.7930N","1 26.6501W","",
+"HA121056","Thornhill Park Rd os 142 NW","","50 54.8809N","1 19.7561W","",
+"HA121057","Thornhill Park Rd nr Moorhill Rd SE","","50 54.8802N","1 19.7348W","",
+"HA122972","Redbridge Causeway off-slip NE","","50 55.3349N","1 28.2946W","",
+"HA12549A","Southampton Coach Stn Harbour Parade NE","","50 54.3576N","1 24.5604W","",
+"HA140020","Common Rd at jnc The Street SE","","51 0.6817N","1 39.0639W","",
+"HAA09127","Winchester Station Stnd A SE","","51 4.0330N","1 19.1376W","",
+"HAA09198","Hamble School grounds","","50 52.4021N","1 19.5572W","",
+"HAA09202","Ingleside nr Bowcombe SE","","50 52.8497N","1 20.5717W","",
+"HAA09206","Woolston Rd nr Ingleside W","","50 52.9372N","1 20.5841W","",
+"HAA09248","Skys Wood Rd nr Bird Field NE","","50 59.1753N","1 24.5659W","",
+"HAA09339","Applemore College grounds","","50 51.6608N","1 25.8442W","",
+"HAA09360","Balmoral Way opp Betteridge Dr NE","","50 56.9486N","1 27.8210W","",
+"HAA09361","Balmoral Way nr Horns Drove E","","50 57.1215N","1 27.2894W","",
+"HAA09362","Balmoral Way nr Hann Rd W","","50 57.1130N","1 27.3271W","",
+"HAA09363","Balmoral Way Betteridge Dr SW","","50 56.9437N","1 27.8168W","",
+"HAA09424","Southampton Parkway opp Station S","","50 56.9971N","1 21.7961W","",
+"HAA09425","Wide Ln os Ln keside Country Park NE","","50 57.2959N","1 21.5793W","",
+"HAA09426","Wide Ln opp Ln keside Country Park SW","","50 57.3007N","1 21.5648W","",
+"HAA09578","Tollbar Way nr Wellstead Way N","","50 55.8713N","1 18.5056W","",
+"HAA10020","Grange Rd nr Woodhouse Ln E","","50 54.9677N","1 17.2907W","",
+"HAA10043","Passfield Ave opp Fleming Park SW","","50 58.1896N","1 22.1140W","",
+"HAA10044","Passfield Ave os Fleming Park NE","","50 58.1644N","1 22.1314W","",
+"HAA10056","Wildern School Grounds","","50 55.0771N","1 18.1554W","",
+"HAA10104","Balmoral Way nr Hurricane Dr W","","50 57.0382N","1 27.5860W","",
+"HAA10105","Balmoral Way opp Normandy Cl E","","50 57.0379N","1 27.6329W","",
+"HAA10110","Passfield Ave nr Cedar Rd N","","50 57.7516N","1 22.2361W","",
+"HAA10111","Passfield Ave nr Cedar Rd S","","50 57.7704N","1 22.2213W","",
+"HAA13371","Vincents Walk os Primark N","","50 54.2374N","1 24.1651W","",
+"HAA13373","Westwood Rd os Cranleigh Hse SW","","50 55.3808N","1 24.0838W","",
+"HAA13374","Westwood Rd os Kinterbury Ct NE","","50 55.3948N","1 24.0691W","",
+"HAA13375","Westwood Rd os Elm Ct NE","","50 55.4806N","1 23.8708W","",
+"HAA13376","Westwood Rd os Pembroke Ct SW","","50 55.4784N","1 23.8572W","",
+"HAA13377","Westwood Rd os Albany Park Ct NE","","50 55.3436N","1 24.1902W","",
+"HAA13379","Langhorn Rd os 71 SE","","50 56.2844N","1 23.0168W","",
+"HAA13380","Langhorn Rd os 5 SE","","50 56.2266N","1 22.8971W","",
+"HAA13381","Langhorn Rd nr Portswood Rd NW","","50 56.2065N","1 22.8701W","",
+"HAA13383","Frogmore Ln opp Bargain Farm E","","50 56.1725N","1 28.0016W","",
+"HAA13385","Franconia Dr nr Mauretania Rd N","","50 56.1489N","1 28.6218W","",
+"HAA13386","Wide Ln os 43 NE","","50 56.5967N","1 22.2850W","",
+"HAA13387","Leaside Way os St Georges Sch E","","50 56.7226N","1 22.9264W","",
+"HAA13388","Lords Hill Way Woburn Flyover W","","50 56.6035N","1 25.9256W","",
+"HAA13389","Lords Hill Way nr Tanners Brook SW","","50 56.5360N","1 26.2467W","",
+"HAA13545","Milford Rd os Priestlands Sch NE","","50 45.1720N","1 33.1347W","",
+"HAA13562","A36 nr Lyndhurst Rd B3076 NW","","50 58.8896N","1 38.2602W","",
+"HAA13579","National Oceanography Centre forecourt","","50 53.6076N","1 23.7167W","",
+"HAA13580","Town Quay os Red Funnel SW","","50 53.7664N","1 24.2820W","",
+"HAA13582","Portland Ter os West Quay 1 NW","","50 54.1855N","1 24.3483W","",
+"HAA13583","Portland Ter opp West Quay 2 SE","","50 54.2162N","1 24.3437W","",
+"HAA13584","Civic Centre Rd opp Civic Cnt E","","50 54.4080N","1 24.3865W","",
+"HAA13647","Castle Way nr Bargate St NW","","50 54.1493N","1 24.3377W","",
+"HAA13649","West Quay Rd opp LW SE","","50 54.1883N","1 24.7024W","",
+"HAA13650","Wessex Ln os Montefiore Halls N","","50 56.3623N","1 22.5503W","",
+"HAA13651","Wessex Ln opp Montefiore Halls S","","50 56.3628N","1 22.5443W","",
+"HAA13652","Archery Rd opp 118 NW","","50 53.3084N","1 22.3463W","",
+"HAA13653","Archery Rd opp 37 SE","","50 53.3788N","1 22.3923W","",
+"HAA13654","Jurds Lake Way nr Weston Ln S","","50 53.2859N","1 22.3748W","",
+"HAA13655","Rothschild Cl opp Jurds Ln ke Way E","","50 53.2676N","1 22.3827W","",
+"HAA13657","Jurds Lake Way nr Arrow Cl W","","50 53.3836N","1 22.5808W","",
+"HAA13658","Jurds Lake Way opp Arrow Cl E","","50 53.3885N","1 22.5927W","",
+"HAA13659","Victoria Rd nr Taylor Cl SE","","50 53.3834N","1 22.7446W","",
+"HAA13660","Victoria Rd nr Unwin Cl NW","","50 53.3857N","1 22.7659W","",
+"HAA13661","Victoria Rd nr Dundonald Cl SW","","50 53.3998N","1 22.8774W","",
+"HAA13662","Victoria Rd opp Dundonald Cl NE","","50 53.4004N","1 22.8945W","",
+"HAA13663","Victoria Rd nr Swift Rd S","","50 53.4537N","1 22.9816W","",
+"HAA13664","Victoria Rd so sewage works NE","","50 53.4683N","1 22.9857W","",
+"HAA13665","Kathleen Rd os 111 NE","","50 54.1554N","1 21.0456W","",
+"HAA13668","Univ Interchange NW","","50 56.1758N","1 23.8098W","",
+"HAA13694","Tollbar Way os Berrywood Vill NE","","50 55.9964N","1 18.4935W","",
+"HAA13695","Tollbar Way opp Berrywood Vill SW","","50 55.9952N","1 18.4867W","",
+"HAA19442","Hamble Ln nr Satchell Ln S","","50 52.4817N","1 19.6976W","",
+"HAA19443","Hamble Ln nr Satchell Ln N","","50 52.4925N","1 19.7137W","",
+"HAA19444","Hamble Ln os 92 S","","50 52.0400N","1 19.6528W","",
+"HAA19694","Nichol Rd os 54 SW","","51 0.1316N","1 22.7392W","",
+"HAA19695","Nichol Rd os 57 NE","","51 0.1306N","1 22.7469W","",
+"HAA19700","Rownhams Ln nr The Mews NW","","50 57.0113N","1 27.1430W","",
+"HAA19701","Rownhams Ln nr The Mews SE","","50 57.0075N","1 27.1302W","",
+"HAA19705","Hook Rd os Potters Heron N","","51 0.4099N","1 24.8050W","",
+"HAA40520","Bargate St nr High St E - RTI ghost","","50 54.1706N","1 24.2777W","",
+"HAA90784","Lymington New Forest Hospital Entrance","","50 46.1655N","1 32.7721W","",
+"HAA91092","Adanac Way nr Ordnance Survey NW","","50 56.1236N","1 28.1611W","",
+"MG1031","NOC arival - RTI ghost","","50 53.5977N","1 23.6801W","",
+"SN100809","Romsey Rd nr Redbridge Ln NW","","50 56.6174N","1 27.5917W","",
+"SN100810","Bakers Droe nr Romsey Rd NE","","50 56.6279N","1 27.5446W","",
+"SN120004","Royal South Hants Hospital nr Chapel","","50 54.7772N","1 23.7980W","",
+"SN120006","Wimpson Ln os 317 NE","","50 55.7222N","1 27.0019W","",
+"SN120007","Wimpson Ln os 336 to 350 SW","","50 55.6915N","1 27.0261W","",
+"SN120008","Lords Hill Way path to Dunbar Cl NE","","50 56.6125N","1 26.8949W","",
+"SN120009","Lords Hill Way path to Blackbushe Cl SW","","50 56.6081N","1 26.8787W","",
+"SN120010","Lords Hill Way path to Pemburey Cl NW","","50 56.6082N","1 26.6660W","",
+"SN120011","Lords Hill Way os playing fields SE","","50 56.5944N","1 26.6038W","",
+"SN120013","Lords Hill Way nr Tanners Brook NE","","50 56.5579N","1 26.2003W","",
+"SN120014","Lords Hill Way Woburn Flyover E","","50 56.6191N","1 25.9229W","",
+"SN120017","Bakers Drove nr Ln keside Ave SW","","50 56.7829N","1 27.3378W","",
+"SN120019","Buchanan Rd nr Fraser Cl NE","","50 56.7875N","1 26.9406W","",
+"SN120023","Buchanan Rd nr Forbes Cl NE","","50 56.8173N","1 26.8600W","",
+"SN120024","Matheson Rd os 59 E","","50 56.7718N","1 26.7051W","",
+"SN120025","Sutherland Rd os Erskine Ct W","","50 56.7160N","1 26.7758W","",
+"SN120026","Sutherland Rd nr 2 SW","","50 56.6636N","1 26.9899W","",
+"SN120028","Lobelia Rd nr Lupin Rd SW","","50 56.6138N","1 23.2737W","",
+"SN120031","Lobelia Rd nr Bassett Green Rd NE","","50 56.6263N","1 23.2796W","",
+"SN120032","Bassett Gn Rd opp 84 E","","50 56.6162N","1 23.0978W","",
+"SN120033","Bassett Gn Rd os 88 W","","50 56.6114N","1 23.1260W","",
+"SN120034","Bassett Gn Rd opp 54 E","","50 56.6038N","1 22.9083W","",
+"SN120039","Lobelia Rd os 32 S","","50 56.5368N","1 23.2876W","",
+"SN120040","Mansbridge Rd opp 2 SE","","50 56.4843N","1 22.3591W","",
+"SN120041","Lower Brownhill Rd nr Boniface Cres NE","","50 56.0917N","1 27.6729W","",
+"SN120042","Lower Brownhill Rd nr Boniface Cres SW","","50 56.0725N","1 27.7269W","",
+"SN120043","Lords Hill Way nr Fairisle Rd NE","","50 56.4227N","1 27.1644W","",
+"SN120045","Lords Hill opp Sainsburys NE","","50 56.5027N","1 27.0798W","",
+"SN120046","Lords Hill Way os Sainsburys 1 SW","","50 56.5153N","1 26.9993W","",
+"SN120047","Lords Hill Way os Sainsburys 2 SW","","50 56.5094N","1 27.0156W","",
+"SN120048","Lords Hill os library SE","","50 56.3890N","1 26.9812W","",
+"SN120049","Lords Hill opp library NW","","50 56.3863N","1 26.9906W","",
+"SN120050","Lords Hill Way opp Fairisle Sch SW","","50 56.4108N","1 27.1517W","",
+"SN120051","Romsey Rd nr Lords Hill Way NW","","50 56.4548N","1 27.4433W","",
+"SN120052","Lower Brownhill Rd opp Corbiere Cl NE","","50 56.1250N","1 27.5351W","",
+"SN120053","Lower Brownhill Rd nr Corbiere Cl SW","","50 56.1292N","1 27.4966W","",
+"SN120054","Lower Brownhill Rd nr Boniface Cres NE","","50 56.1774N","1 27.3107W","",
+"SN120055","Lower Brownhill Rd nr Boniface Cres SW","","50 56.1794N","1 27.2808W","",
+"SN120056","Upper Brownhill Rd opp 29 NE","","50 56.2297N","1 27.0770W","",
+"SN120057","Upper Brownhill Rd opp 59 NE","","50 56.2610N","1 26.9520W","",
+"SN120059","Upper Brownhill Rd os 51 SW","","50 56.2508N","1 26.9768W","",
+"SN120061","Upper Brownhill Rd os 95 SW","","50 56.2884N","1 26.8244W","",
+"SN120062","Romsey Rd os 489 SW","","50 56.0608N","1 27.0687W","",
+"SN120063","Upper Brownhill Rd opp 6 NE","","50 56.3150N","1 26.7353W","",
+"SN120065","Aldermoor Rd opp Springford Rd SE","","50 56.4399N","1 26.0130W","",
+"SN120066","Aldermoor Rd os 22 SW","","50 56.3312N","1 26.6420W","",
+"SN120067","Aldermoor Ave os 47 NW","","50 56.3389N","1 26.4310W","",
+"SN120069","Aldermoor Rd opp 44 NE","","50 56.3678N","1 26.5015W","",
+"SN120070","Aldermoor Rd os 72 SW","","50 56.3899N","1 26.3919W","",
+"SN120071","Aldermoor Rd nr Springford Rd NW","","50 56.4427N","1 26.0352W","",
+"SN120072","Aldermoor Ave nr Palm Rd NW","","50 56.1911N","1 26.3294W","",
+"SN120073","Aldermoor Ave nr Palm Rd SE","","50 56.1863N","1 26.3414W","",
+"SN120076","Palm Rd opp 44 NE","","50 56.1533N","1 26.5451W","",
+"SN120077","Palm Rd nr Olive Rd SW","","50 56.1474N","1 26.5537W","",
+"SN120078","Coxford Rd opp 12 NE","","50 56.0347N","1 26.6797W","",
+"SN120079","Coxford Dro os 4 SW","","50 56.0207N","1 26.6850W","",
+"SN120080","Warren Ave os 26 NW","","50 55.9655N","1 26.4218W","",
+"SN120081","Warren Ave nr Ln undry Rd SE","","50 55.9963N","1 26.4325W","",
+"SN120082","Tremona Rd opp 216 NW","","50 56.0735N","1 25.9936W","",
+"SN120083","Coxford Rd opp 247 SW","","50 56.1032N","1 26.0086W","",
+"SN120084","Tremona Rd nr 198 SE","","50 56.0467N","1 25.9205W","",
+"SN120085","Coxford Rd os 289 NE","","50 56.1926N","1 25.8581W","",
+"SN120086","Coxford Rd opp Springford Cres SW","","50 56.2151N","1 25.8296W","",
+"SN120087","Aldermoor Rd nr Shops SE","","50 56.4241N","1 25.7587W","",
+"SN120088","Aldermoor Rd opp Shops W","","50 56.4266N","1 25.8176W","",
+"SN120089","Lords Hill Way nr health centre SE","","50 56.4483N","1 25.7439W","",
+"SN120090","Lords Hill Way nr health centre NW","","50 56.4262N","1 25.7468W","",
+"SN120091","Coxford Rd os Lyburn Ct NE","","50 56.3280N","1 25.7463W","",
+"SN120092","Coxford Rd opp Lyburn Ct SW","","50 56.3344N","1 25.7265W","",
+"SN120093","Lordswood Rd opp 48 SW","","50 56.2663N","1 25.4814W","",
+"SN120094","Lordswood Rd opp 33 W","","50 56.2314N","1 25.4195W","",
+"SN120095","Hill Ln os 177 SE","","50 56.0984N","1 25.1496W","",
+"SN120096","Hill Ln os 380 NW","","50 56.1191N","1 25.1733W","",
+"SN120097","Winchester Rd os 390 NE","","50 56.0879N","1 25.0849W","",
+"SN120098","Winchester Rd os 361A SW","","50 56.0766N","1 25.0902W","",
+"SN120099","Hill Ln opp 352 SE","","50 56.0021N","1 25.0945W","",
+"SN120100","Hill Ln os 352 NW","","50 55.9995N","1 25.1014W","",
+"SN120102","Coxford Rd opp 175 SW","","50 56.0445N","1 26.2467W","",
+"SN120108","Highfield Ln nr Highfield Rd SE","","50 55.9575N","1 24.1678W","",
+"SN120109","Highfield Ln opp 1 SE","","50 55.9141N","1 24.1180W","",
+"SN120111","Winchester Rd nr Bassett Avenue NE","","50 56.4140N","1 24.4967W","",
+"SN120112","Winchester Rd nr Butterfield Rd NE","","50 56.2905N","1 24.7126W","",
+"SN120113","Winchester Rd opp 478 SW","","50 56.2497N","1 24.7618W","",
+"SN120114","Winchester Rd nr Bassett Avenue SW","","50 56.4177N","1 24.4744W","",
+"SN120115","Bassett Ave opp 51 S","","50 56.3547N","1 24.4010W","",
+"SN120116","Bassett Ave nr Chetwynd Rd S","","50 56.5015N","1 24.3914W","",
+"SN120117","Bassett Ave os 49 N","","50 56.3445N","1 24.4096W","",
+"SN120118","Bassett Ave nr Burgess Rd N","","50 56.2198N","1 24.3993W","",
+"SN120119","Bassett Ave nr Burgess Rd S","","50 56.2090N","1 24.3874W","",
+"SN120120","Burgess Rd nr Bassett Ave SW","","50 56.1814N","1 24.2657W","",
+"SN120121","Burgess Rd nr Bassett Ave NE","","50 56.1980N","1 24.2484W","",
+"SN120123","Violet Rd os Cantell sch SE - RTI ghost","","50 56.4776N","1 23.9442W","",
+"SN120124","Glen Eyre Rd opp Hartley Grove Hall SE","","50 56.4744N","1 24.0570W","",
+"SN120125","Glen Eyre Rd os Hartley Grove Hall NW","","50 56.4550N","1 24.0572W","",
+"SN120126","Glen Eyre Rd os 5 SE","","50 56.3143N","1 23.9805W","",
+"SN120127","Burgess Rd os Holmwood Ct NE","","50 56.2499N","1 24.0411W","",
+"SN120128","Burgess Rd opp 189 SW","","50 56.2572N","1 23.9940W","",
+"SN120129","Violet Rd os 43 SE","","50 56.4123N","1 23.7298W","",
+"SN120130","Violet Rd os 58 SE - RTI ghost","","50 56.4110N","1 23.7000W","",
+"SN120131","Burgess Rd nr library E","","50 56.2878N","1 23.7579W","",
+"SN120134","University Rd opp Stile ph S","","50 56.2614N","1 23.7788W","",
+"SN120136","Burgess Rd opp 259 W","","50 56.2894N","1 23.6631W","",
+"SN120137","Burgess Rd os 345 E","","50 56.3190N","1 23.3203W","",
+"SN120138","Honeysuckle Rd os 96 E","","50 56.3438N","1 23.5266W","",
+"SN120139","Burgess Rd os 305 E","","50 56.3142N","1 23.4442W","",
+"SN120140","Burgess Rd os 202 W","","50 56.3032N","1 23.5075W","",
+"SN120141","Lobelia Rd nr Copperfield Rd N","","50 56.4376N","1 23.3153W","",
+"SN120142","Lobelia Rd nr 39 N","","50 56.4904N","1 23.3044W","",
+"SN120143","Lobelia Rd nr Bluebell Rd S","","50 56.4327N","1 23.3069W","",
+"SN120144","Burgess Rd opp Woodcote Rd E","","50 56.3146N","1 23.2094W","",
+"SN120145","Burgess Rd W opp Tulip Rd W","","50 56.3101N","1 23.2752W","",
+"SN120146","Burgess Rd os 399 NE","","50 56.3120N","1 23.0343W","",
+"SN120147","Burgess Rd os Methodist ch W","","50 56.3043N","1 23.1036W","",
+"SN120148","Stoneham Ln opp Mkt Blds NW","","50 56.4267N","1 22.7869W","",
+"SN120149","Stoneham Ln os Mkt Blds SE","","50 56.4370N","1 22.7816W","",
+"SN120150","High Rd opp 64 N","","50 56.3357N","1 22.8086W","",
+"SN120151","High Rd os 52 S","","50 56.3130N","1 22.8046W","",
+"SN120153","High Rd os 9 N","","50 56.2208N","1 22.8272W","",
+"SN120157","Portswood Rd os B & Q NE","","50 56.0718N","1 22.9111W","",
+"SN120158","Portswood Rd os 508 SW","","50 56.0337N","1 22.9475W","",
+"SN120159","Portswood Rd os 615-619 NE","","50 55.9458N","1 23.0571W","",
+"SN120160","Wessex Ln os Montefiore Halls NE","","50 56.2445N","1 22.6100W","",
+"SN120161","Wessex Ln opp Montefiore entrance SW","","50 56.2354N","1 22.6229W","",
+"SN120162","Wessex Ln os 7 NE","","50 56.5051N","1 22.5023W","",
+"SN120163","Wessex Ln opp 9 SW","","50 56.4997N","1 22.4998W","",
+"SN120164","Wide Ln opp 33 SW","","50 56.5747N","1 22.3041W","",
+"SN120165","Mansbridge Rd opp Octavia Rd SE","","50 56.4411N","1 22.1530W","",
+"SN120171","Meggeson Ave turning circle SW","","50 55.9738N","1 21.7427W","",
+"SN120174","Mansel Rd West os Saints ph SE","","50 55.8041N","1 27.7830W","",
+"SN120175","Windermere Ave nr Mansel Rd West NE","","50 55.8098N","1 27.7351W","",
+"SN120177","Kendal Ave nr Mansel Rd West SW","","50 55.7598N","1 27.7826W","",
+"SN120178","Kendal Ave opp ch N","","50 55.6096N","1 27.8544W","",
+"SN120179","Kendal Ave nr Perran Rd S","","50 55.5691N","1 27.8463W","",
+"SN120180","Kendal Ave os Shops SE","","50 55.4633N","1 27.8227W","",
+"SN120181","Kendal Ave opp Shops NW","","50 55.4584N","1 27.8313W","",
+"SN120182","Windermere Ave os 142-156 SE","","50 55.8071N","1 27.5106W","",
+"SN120183","Windermere Ave os Millbrook Towers NW","","50 55.8148N","1 27.5498W","",
+"SN120184","Windermere Ave opp 86 NW","","50 55.7262N","1 27.3911W","",
+"SN120185","Windermere Ave os 74 SE","","50 55.7125N","1 27.3571W","",
+"SN120186","Windermere Ave os 26-36 SE","","50 55.6612N","1 27.2374W","",
+"SN120187","Windermere Ave nr 15-25 NW","","50 55.6542N","1 27.2332W","",
+"SN120188","Wimpson Ln opp Bush ph SW","","50 55.7844N","1 26.9320W","",
+"SN120194","Rownhams opp Coxford Rd NE","","50 55.8834N","1 26.8719W","",
+"SN120196","Romsey Rd nr path to Thorndyke Rd SE","","50 55.8332N","1 26.8554W","",
+"SN120203","Romsey Rd os 309 SE","","50 55.6960N","1 26.7119W","",
+"SN120204","Romsey Rd opp 273 NW","","50 55.6705N","1 26.6849W","",
+"SN120207","Romsey Rd opp 241 NW","","50 55.6172N","1 26.6027W","",
+"SN120208","Romsey Rd nr Arliss Rd SE","","50 55.6362N","1 26.6187W","",
+"SN120209","Warren Ave os 63 SE","","50 55.8842N","1 26.3605W","",
+"SN120210","Warren Ave os 86 NW","","50 55.8491N","1 26.3481W","",
+"SN120211","Warren Ave os 148 NW","","50 55.7376N","1 26.2760W","",
+"SN120213","Warren Ave opp 170 SE","","50 55.6932N","1 26.2373W","",
+"SN120214","Warren Ave os 222 NW","","50 55.6012N","1 26.1880W","",
+"SN120216","Romsey Rd opp King Edward Ave SE","","50 55.5254N","1 26.3631W","",
+"SN120217","Romsey Rd opp 123 NW","","50 55.5134N","1 26.3368W","",
+"SN120218","Tremona Rd opp 130 NE","","50 55.8877N","1 25.9694W","",
+"SN120219","Tremona Rd os 120-122 SW","","50 55.8679N","1 25.9858W","",
+"SN120220","Anglesea Rd os 19 SW","","50 55.4782N","1 26.0777W","",
+"SN120221","Tremona Rd opp 154 NE","","50 55.9317N","1 25.9133W","",
+"SN120222","Tremona Rd nr 168 SW","","50 55.9748N","1 25.8889W","",
+"SN120223","Dale Rd opp 59 SE","","50 55.8639N","1 25.8390W","",
+"SN120224","Dale Rd nr Winchester Rd SE","","50 55.7539N","1 25.7396W","",
+"SN120225","Dale Rd opp 16 NW","","50 55.7799N","1 25.7726W","",
+"SN120226","Winchester Rd os 170 NE","","50 55.6881N","1 25.8634W","",
+"SN120227","Winchester Rd opp 158 SW","","50 55.6742N","1 25.8806W","",
+"SN120228","Winchester Rd os 216 NE","","50 55.7553N","1 25.6927W","",
+"SN120230","Wilton Rd os 5 NW","","50 55.7576N","1 25.6073W","",
+"SN120231","Winchester Rd os Currys SW","","50 55.8075N","1 25.5631W","",
+"SN120232","Winchester Rd os Malvern ph NE","","50 55.9114N","1 25.4115W","",
+"SN120233","Winchester Rd opp 308 SW","","50 55.9365N","1 25.3489W","",
+"SN120234","Bellemoor Rd os 92 SE","","50 55.6816N","1 25.3094W","",
+"SN120235","Wilton Rd os 60 SE","","50 55.6545N","1 25.5018W","",
+"SN120236","Wilton Rd os 85 NW","","50 55.6209N","1 25.4775W","",
+"SN120237","Wilton Rd os 100 SE","","50 55.5613N","1 25.4108W","",
+"SN120238","Upper Shirley Ave os 120 NE","","50 55.5203N","1 25.4207W","",
+"SN120239","Upper Shirley Ave nr St James Rd SW","","50 55.4643N","1 25.5443W","",
+"SN120240","Bellemoor Rd os 123 NW","","50 55.6712N","1 25.2762W","",
+"SN120242","Hill Ln os 316 NW","","50 55.8465N","1 25.0452W","",
+"SN120243","Hill Ln opp 312 SE","","50 55.8319N","1 25.0326W","",
+"SN120245","Hill Ln opp Bellemoor ph SE","","50 55.6523N","1 24.9554W","",
+"SN120246","Hill Ln os Tauntons College NW","","50 55.5956N","1 24.9391W","",
+"SN120247","Hill Ln opp 230 S","","50 55.4843N","1 24.9029W","",
+"SN120248","Hill Ln os 220 N","","50 55.4492N","1 24.9093W","",
+"SN120256","University Rd opp sports centre SE","","50 56.0477N","1 23.7679W","",
+"SN120257","University Rd os sports centre NW","","50 56.0494N","1 23.7798W","",
+"SN120261","Highfield Ln os Highfield ph SE","","50 55.8589N","1 23.9889W","",
+"SN120263","Highfield Ln os 68-78 NW","","50 55.8403N","1 23.9354W","",
+"SN120264","Highfield Ln opp 104-108 SE","","50 55.7974N","1 23.7711W","",
+"SN120265","Highfield Ln os 100 NW","","50 55.7991N","1 23.7959W","",
+"SN120266","Welbeck Ave os 63 SE","","50 55.8714N","1 23.4824W","",
+"SN120267","Welbeck Ave os 62 NW","","50 55.8638N","1 23.4680W","",
+"SN120268","Shaftesbury Ave os Chestnut Ct N","","50 55.7746N","1 23.4444W","",
+"SN120269","Shaftesbury Ave os 24 SW","","50 55.7229N","1 23.4519W","",
+"SN120270","Highfield Ln opp 132 SE","","50 55.6721N","1 23.5508W","",
+"SN120271","Highfield Ln os 132 NW","","50 55.6684N","1 23.5568W","",
+"SN120273","St Denys Rd os Pizza Hut SE","","50 55.5843N","1 23.4614W","",
+"SN120274","St Denys Rd os Mitre ph NW","","50 55.5852N","1 23.4298W","",
+"SN120276","Brookvale Rd opp video shop SE","","50 55.4931N","1 23.6752W","",
+"SN120278","Brookvale Rd os video shop NW","","50 55.4872N","1 23.6710W","",
+"SN120279","Portswood Rd os Waitrose NE","","50 55.4548N","1 23.6680W","",
+"SN120280","Winn Rd os 40 SW","","50 55.5274N","1 23.9445W","",
+"SN120281","Winn Rd opp Tennyson Ct NE","","50 55.5488N","1 23.9101W","",
+"SN120282","Winn Rd os Bentley Ct NE","","50 55.4587N","1 24.1161W","",
+"SN120283","Winn Rd opp Raglan Ct SW","","50 55.4426N","1 24.1385W","",
+"SN120284","Portswood Rd nr Grosvenor Rd NE","","50 55.6548N","1 23.3239W","",
+"SN120285","Portswood Rd nr Belmont Rd SW","","50 55.6388N","1 23.3625W","",
+"SN120287","Portswood Rd opp 603-607 SW","","50 55.9318N","1 23.0573W","",
+"SN120289","Portswood Rd opp RC ch N","","50 55.7848N","1 23.1164W","",
+"SN120290","Woodmill Ln os 181 W","","50 55.9709N","1 22.2012W","",
+"SN120291","Oaktree Rd os Hop ph SW","","50 55.9592N","1 22.2415W","",
+"SN120292","Oaktree Rd os 126 NE","","50 55.8722N","1 22.4066W","",
+"SN120293","Oaktree Rd opp 134 SW","","50 55.8865N","1 22.3663W","",
+"SN120294","St Catherines Rd opp 9 Cobden Rise S","","50 55.4155N","1 22.4768W","",
+"SN120295","Oaktree Rd opp 56 SW","","50 55.7562N","1 22.5158W","",
+"SN120296","St Catherines Rd os 35 S","","50 55.5261N","1 22.4676W","",
+"SN120297","Woodmill Ln os 1-137 SE","","50 55.9006N","1 22.0792W","",
+"SN120300","Portswood Rd opp 471 S","","50 55.7486N","1 23.1101W","",
+"SN120302","St Denys Rd os 20 SE","","50 55.5176N","1 23.3086W","",
+"SN120308","Manor Farm Rd opp Triangle clock NE","","50 55.4764N","1 22.5605W","",
+"SN120309","Bitterne Triangle nr clock SE - RTI ghos","","50 55.4603N","1 22.5641W","",
+"SN120310","Cobden Bridge nr eastern river-bank W","","50 55.4612N","1 22.6307W","",
+"SN120311","Nursery Rd os 9 E","","50 55.6429N","1 22.6044W","",
+"SN120312","Oaktree Rd os 48 NE","","50 55.7417N","1 22.5305W","",
+"SN120313","St Catherines Rd os 61 SE","","50 55.6144N","1 22.5339W","",
+"SN120314","Woodmill Ln os 71 NW","","50 55.7348N","1 21.9355W","",
+"SN120315","Witts Hill opp Trent Rd SE","","50 55.5703N","1 21.8532W","",
+"SN120316","Witts Hill os shops NW","","50 55.5551N","1 21.8449W","",
+"SN120319","Meggeson Ave os 222-252 SE","","50 55.8390N","1 21.5618W","",
+"SN120326","South Mill Rd nr King George Ave W","","50 54.9779N","1 26.8314W","",
+"SN120329","King Georges Ave os 164 SW","","50 55.1938N","1 26.7503W","",
+"SN120330","King Georges Ave os 92 S","","50 55.0394N","1 26.8435W","",
+"SN120334","Kendal Ave nr Windrush Rd SE","","50 55.3140N","1 27.5095W","",
+"SN120335","Kendal Ave nr Windrush Rd NW","","50 55.3124N","1 27.5334W","",
+"SN120338","Cumbrian Way opp 18 E","","50 55.2697N","1 27.2701W","",
+"SN120339","Cumbrian Way os 2 NW","","50 55.2701N","1 27.3623W","",
+"SN120340","Wimpson Ln os 16 SE","","50 55.1613N","1 27.4028W","",
+"SN120341","Wimpson Ln opp 14 NW","","50 55.1549N","1 27.4089W","",
+"SN120344","Bursledon Rd os 194-224 SE","","50 54.1993N","1 20.1149W","",
+"SN120345","Orpen Rd nr Bursledon Rd SW","","50 54.2284N","1 20.2075W","",
+"SN120346","Cumbrian Way os housing office NE","","50 55.2922N","1 27.1282W","",
+"SN120347","Cumbrian Way os 42 SW","","50 55.2762N","1 27.1659W","",
+"SN120348","Cumbrian Way nr 89 NE","","50 55.3505N","1 27.0097W","",
+"SN120349","Cumbrian Way os 80 SW","","50 55.3279N","1 27.0321W","",
+"SN120350","Oakley Rd os 148 NW","","50 55.3368N","1 26.8605W","",
+"SN120351","Oakley Rd opp 148 SE","","50 55.3411N","1 26.8630W","",
+"SN120352","King Georges Ave os 93 N","","50 55.0352N","1 26.8538W","",
+"SN120354","King Georges Ave os 169 NE","","50 55.2122N","1 26.7467W","",
+"SN120355","Oakley Rd os 94 NE","","50 55.3067N","1 26.6517W","",
+"SN120357","Regents Pk Rd opp 80 NE","","50 55.0010N","1 26.4863W","",
+"SN120358","Regents Pk Rd os 68 SW","","50 54.9844N","1 26.4968W","",
+"SN120360","Oakley Rd opp 74 SE","","50 55.3202N","1 26.5405W","",
+"SN120361","Oakley Rd opp sch sports area NW","","50 55.2989N","1 26.4845W","",
+"SN120362","Oakley Rd opp 60 SW","","50 55.2943N","1 26.4273W","",
+"SN120363","Regents Pk Rd opp 148 NE","","50 55.1283N","1 26.3482W","",
+"SN120364","Regents Pk Rd os 138 SW","","50 55.1056N","1 26.3579W","",
+"SN120365","Regents Pk Rd opp 206 NE","","50 55.2931N","1 26.1849W","",
+"SN120366","Regents Pk Rd os Denison Ct SW","","50 55.2609N","1 26.2118W","",
+"SN120367","Shirley High St os precinct 2 SE","","50 55.4135N","1 26.0938W","",
+"SN120371","Shirley High St os 50 KFC NW","","50 55.3180N","1 25.9848W","",
+"SN120372","Shirley High St opp Emsworth Rd SE","","50 55.2898N","1 25.9382W","",
+"SN120373","Shirley Ave os 84 NE","","50 55.4392N","1 25.6078W","",
+"SN120374","Shirley Ave os PO NE","","50 55.2650N","1 25.8429W","",
+"SN120375","Shirley Ave os 5 SW","","50 55.2762N","1 25.8180W","",
+"SN120376","Shirley Rd os 411 SE","","50 55.1953N","1 25.8165W","",
+"SN120377","Shirley Rd os police station NW","","50 55.2257N","1 25.8665W","",
+"SN120378","Shirley Ave os 73 SW","","50 55.4258N","1 25.6156W","",
+"SN120380","Shirley Rd os 330 NW","","50 55.0498N","1 25.6399W","",
+"SN120381","Shirley Rd os 297 SE","","50 55.0226N","1 25.5924W","",
+"SN120382","Regents Park Rd os 160 SW","","50 55.1663N","1 26.3008W","",
+"SN120383","Regents Park Rd opp 174 NW","","50 55.1959N","1 26.2868W","",
+"SN120384","St James Rd os 82 SE","","50 55.4034N","1 25.4622W","",
+"SN120385","St James Rd os 91 NW","","50 55.3834N","1 25.4428W","",
+"SN120386","St James Rd os ch NW","","50 55.2179N","1 25.2554W","",
+"SN120387","St James Rd opp 3 SE","","50 55.2352N","1 25.2654W","",
+"SN120388","Hill Ln opp Wilton Rd S","","50 55.2884N","1 24.9071W","",
+"SN120389","Hill Ln os 202 N","","50 55.2475N","1 24.9272W","",
+"SN120390","Raymond Rd os bowling club E","","50 55.1394N","1 24.9849W","",
+"SN120391","Hill Ln opp bowling club S","","50 55.1525N","1 24.9199W","",
+"SN120392","Hill Ln os 184A N","","50 55.1072N","1 24.9247W","",
+"SN120393","Raymond Rd os 14A W","","50 55.1327N","1 25.0584W","",
+"SN120394","Hill Ln opp 130 S","","50 54.9330N","1 24.9209W","",
+"SN120395","Archers Rd opp 34 NE","","50 54.9861N","1 24.5541W","",
+"SN120396","Archers Rd os 54 SW","","50 54.9458N","1 24.6809W","",
+"SN120397","Archers Rd os Dorrick Ct W","","50 54.9938N","1 24.4610W","",
+"SN120398","The Avenue nr Cowherds ph N","","50 55.3334N","1 24.3107W","",
+"SN120399","Winn Rd nr The Avenue W","","50 55.3922N","1 24.2911W","",
+"SN120400","The Avenue os Avenue St Andrews ch S","","50 55.2691N","1 24.2850W","",
+"SN120401","The Ave os 69A SE","","50 55.1346N","1 24.2449W","",
+"SN120402","Carlton Rd opp 54 S","","50 54.9761N","1 24.3827W","",
+"SN120403","Lodge Rd os Travelodge W","","50 55.1327N","1 24.1980W","",
+"SN120404","The Ave os 35 SE","","50 55.0992N","1 24.1942W","",
+"SN120405","The Ave nr Archers Rd NW","","50 54.9518N","1 24.1730W","",
+"SN120406","The Ave os 15-16 TGWU office SE","","50 54.9840N","1 24.1427W","",
+"SN120407","Lodge Rd os 96 NE","","50 55.1475N","1 24.0322W","",
+"SN120408","Lodge Rd os 85 SW","","50 55.1536N","1 23.9519W","",
+"SN120409","Bevois Val opp Aldi Store N","","50 55.0667N","1 23.7371W","",
+"SN120410","Bevois Valley Rd os 64-68 SW","","50 55.0127N","1 23.7446W","",
+"SN120411","Bevois Val opp Forster Rd S","","50 55.1572N","1 23.7154W","",
+"SN120412","Portswood Rd opp 31 S","","50 55.2538N","1 23.7201W","",
+"SN120413","Portswood Rd os 51 N","","50 55.2905N","1 23.7316W","",
+"SN120415","Portswood Rd opp 119 SW","","50 55.4230N","1 23.6829W","",
+"SN120430","Garfield Rd os 5 SE","","50 55.0080N","1 22.4498W","",
+"SN120431","Bitterne Rd opp 199 SE","","50 55.0151N","1 22.2534W","",
+"SN120432","Garfield Rd os 16 SE","","50 54.9919N","1 22.3570W","",
+"SN120433","Cross Rd os 24 S","","50 54.9560N","1 22.3020W","",
+"SN120434","Chessel Ave opp 100 NW","","50 54.9252N","1 22.2956W","",
+"SN120435","Mousehole Ln opp 60A E","","50 55.2456N","1 21.8730W","",
+"SN120438","Witts Hill os 108 NE","","50 55.4025N","1 21.6660W","",
+"SN120442","Townhill Way opp Bramble Mews NE","","50 55.3006N","1 21.3823W","",
+"SN120443","Townhill nr Bramble Mews SW","","50 55.2807N","1 21.3868W","",
+"SN120447","West End Rd opp Dean Ct NE","","50 55.2161N","1 21.4090W","",
+"SN120449","West End Rd os Dean Ct SW","","50 55.2128N","1 21.4023W","",
+"SN120450","West End Rd os 95 NE","","50 55.0754N","1 21.5364W","",
+"SN120451","West End Rd os 62 SW","","50 55.0468N","1 21.5454W","",
+"SN120457","Bitterne Rd os path to Dean Rd SE","","50 54.8929N","1 21.4118W","",
+"SN120459","Bitterne Rd os 567 E","","50 54.8787N","1 20.9955W","",
+"SN120460","Somerset Ave nr Sunningdale Gdns NE","","50 54.9096N","1 20.8303W","",
+"SN120461","Cheriton Ave opp 100 NE","","50 55.1062N","1 20.1823W","",
+"SN120463","Beauworth Ave nr Bentley Green NW","","50 55.2989N","1 20.4919W","",
+"SN120467","Beauworth Ave nr Exford Ave SE","","50 55.2901N","1 20.4665W","",
+"SN120468","Cheriton Ave os 88 SW","","50 55.0714N","1 20.2305W","",
+"SN120469","Cheriton Ave os 9 SE","","50 55.0565N","1 20.4578W","",
+"SN120470","Cheriton Ave os 2 NW","","50 55.0674N","1 20.4944W","",
+"SN120471","Somerset Ave nr Exford Ave NE","","50 55.0600N","1 20.6071W","",
+"SN120472","Somerset Ave opp Exford Arms ph SW","","50 55.0290N","1 20.6588W","",
+"SN120473","Somerset Ave os 10 Kingdom Hall SW","","50 54.9202N","1 20.7986W","",
+"SN120474","Bitterne Rd opp RC ch W","","50 54.8704N","1 21.3438W","",
+"SN120477","Regents Pk Rd os 5 N","","50 54.8386N","1 26.5949W","",
+"SN120479","Regents Pk Rd os 8 S","","50 54.8299N","1 26.5865W","",
+"SN120494","Waterloo Rd opp 104A SE","","50 54.6770N","1 25.6342W","",
+"SN120495","Waterloo Rd os 57 SE","","50 54.6546N","1 25.4723W","",
+"SN120496","Shirley Rd opp 214 SE","","50 54.8841N","1 25.4132W","",
+"SN120498","Shirley Rd os 178 NW","","50 54.8332N","1 25.3609W","",
+"SN120499","Shirley Rd os 99 SE","","50 54.7203N","1 25.2274W","",
+"SN120501","Shirley Rd os 78 NW","","50 54.6483N","1 25.1899W","",
+"SN120502","Hill Ln opp 74 S","","50 54.7733N","1 24.9306W","",
+"SN120503","Waterloo Rd os 68 NW","","50 54.6453N","1 25.4409W","",
+"SN120504","Archers Rd opp 47 SW","","50 54.9029N","1 24.8462W","",
+"SN120505","Milton Rd os 173 E","","50 54.8285N","1 24.8557W","",
+"SN120506","Hill Ln opp Cinnamon Ct N","","50 54.8478N","1 24.9297W","",
+"SN120507","Milton Rd opp 171 W","","50 54.8226N","1 24.8592W","",
+"SN120508","Newcombe Rd os 76 N","","50 54.8050N","1 24.6981W","",
+"SN120509","Newcombe Rd S opp 82 S","","50 54.8147N","1 24.6928W","",
+"SN120510","Carlton Rd os 2 N","","50 54.8752N","1 24.3822W","",
+"SN120511","Newcombe Rd os 11 S","","50 54.6760N","1 24.6741W","",
+"SN120512","Newcombe Rd opp 1 NW","","50 54.6544N","1 24.6718W","",
+"SN120513","Handel Rd os 66 Devsonshire Rd E","","50 54.6279N","1 24.5518W","",
+"SN120514","Handel Rd opp 2 W","","50 54.6231N","1 24.5758W","",
+"SN120515","Shirley Rd opp 44 SE","","50 54.5781N","1 25.0585W","",
+"SN120516","Shirley Rd os 32 NW","","50 54.5553N","1 25.0315W","",
+"SN120518","Wyndham Pl 1 N","","50 54.4968N","1 24.7796W","",
+"SN120519","Blechynden Ter opp Station E","","50 54.4804N","1 24.7329W","",
+"SN120520","Southampton Station south forecourt E","","50 54.4289N","1 24.7882W","",
+"SN120522","London Rd os Natwest N","","50 54.7105N","1 24.2418W","",
+"SN120523","Commercial Rd opp art gallery E","","50 54.5350N","1 24.4352W","",
+"SN120525","Above Bar St nr 200 S","","50 54.5639N","1 24.2812W","",
+"SN120526","Havelock Rd os police station SE","","50 54.4693N","1 24.4668W","",
+"SN120527","Civic Centre Rd os stop AO Civic Ctr E","","50 54.4213N","1 24.3633W","",
+"SN120533","New Road South os Palmerston Park W","","50 54.4103N","1 24.2107W","",
+"SN120535","London Rd os Ln w Courts N","","50 54.8497N","1 24.1427W","",
+"SN120536","London Rd os Nothern Rock SW","","50 54.8194N","1 24.1226W","",
+"SN120537","Onslow Rd nr Bevois Castle ph NE","","50 54.9011N","1 23.8587W","",
+"SN120538","Onslow Rd os Sikh Centre SW","","50 54.8291N","1 23.9211W","",
+"SN120539","St Marys Rd nr Brintons Ter N","","50 54.7000N","1 23.9944W","",
+"SN120540","St Marys Rd nr Brintons Ter S","","50 54.7032N","1 23.9824W","",
+"SN120542","Brintons Rd os 118 SE","","50 54.5667N","1 23.8801W","",
+"SN120543","Brintons Rd opp 54 NW","","50 54.5138N","1 23.7792W","",
+"SN120545","New Rd os 4 Carronades W","","50 54.4275N","1 23.9911W","",
+"SN120547","Northam Rd os King Alfred ph W","","50 54.4630N","1 23.6493W","",
+"SN120548","Northam Rd opp King Alfred ph E","","50 54.4787N","1 23.6559W","",
+"SN120551","Northam Rd nr Parsonage Rd SW","","50 54.6656N","1 23.2968W","",
+"SN120553","Portland Ter os Asda N","","50 54.3589N","1 24.3991W","",
+"SN120556","Chessel Ave opp 8 NW","","50 54.8078N","1 21.9421W","",
+"SN120557","Chessel Ave os 52 SE","","50 54.8537N","1 22.1489W","",
+"SN120558","Northam Rd nr Radcliffe Rd NE","","50 54.5793N","1 23.3986W","",
+"SN120559","Northam Rd nr Radcliffe Rd SW","","50 54.5738N","1 23.3842W","",
+"SN120560","Chessel Ave os 39 NW","","50 54.8362N","1 22.1005W","",
+"SN120561","Chessel Ave os 2A SE","","50 54.8066N","1 21.9063W","",
+"SN120562","Peartree Ave nr 203 NE","","50 54.7812N","1 21.9049W","",
+"SN120563","Peartree Ave os 179 NE","","50 54.6834N","1 21.9805W","",
+"SN120564","Peartree Ave opp 193 SW","","50 54.7387N","1 21.9277W","",
+"SN120565","Peartree Ave opp 121 SW","","50 54.5645N","1 22.1409W","",
+"SN120566","Peartree Ave os 107 NE","","50 54.5448N","1 22.1855W","",
+"SN120569","Peartree Ave os 51 NE","","50 54.4376N","1 22.3337W","",
+"SN120570","Peartree Ave os Leslie Loader House SW","","50 54.4092N","1 22.3529W","",
+"SN120571","Peartree Ave os 15 NE","","50 54.3614N","1 22.4081W","",
+"SN120575","Maybray King Way nr Bitterne Rd East SE","","50 54.8480N","1 21.3902W","",
+"SN120576","Maybray King Way opp leisure centre NW","","50 54.9007N","1 21.4603W","",
+"SN120577","Bitterne Rd opp 559 W","","50 54.8729N","1 21.0237W","",
+"SN120578","Bursledon Rd os 56-58 NW","","50 54.7496N","1 21.2653W","",
+"SN120579","Bursledon Rd os 103 SE","","50 54.7321N","1 21.2143W","",
+"SN120587","Spring Rd opp 110 NW","","50 54.5103N","1 21.6091W","",
+"SN120588","Spring Rd os 81 NE","","50 54.3998N","1 21.6225W","",
+"SN120589","Spring Rd opp 87 SW","","50 54.3847N","1 21.6244W","",
+"SN120590","Middle Rd os 188 NE","","50 54.2898N","1 21.5327W","",
+"SN120594","Bursledon Rd os 161 SE","","50 54.6164N","1 20.9752W","",
+"SN120595","Bursledon Rd opp 155 NW","","50 54.6203N","1 20.9957W","",
+"SN120596","Bursledon Rd os 198 NW","","50 54.5390N","1 20.8338W","",
+"SN120597","Bursledon Rd opp 214 SE","","50 54.5078N","1 20.7549W","",
+"SN120598","Bursledon Rd os 276 NW","","50 54.4320N","1 20.6160W","",
+"SN120599","Hinkler Rd opp 1 Carey Rd NE","","50 54.4484N","1 20.5577W","",
+"SN120600","Hinkler Rd nr 1 Carey Rd SW","","50 54.4467N","1 20.5509W","",
+"SN120601","Bursledon Rd os 17 Carey Rd SW","","50 54.3991N","1 20.5294W","",
+"SN120602","Kathleen Rd os 252 SW","","50 54.3827N","1 20.5834W","",
+"SN120603","Hinkler Rd opp Byron Rd SW","","50 54.4877N","1 20.4462W","",
+"SN120604","Hinkler Rd opp 460 SW","","50 54.5299N","1 20.2758W","",
+"SN120605","Hinkler Rd nr Byron Rd NE","","50 54.4956N","1 20.4094W","",
+"SN120606","Hinkler Rd opp 366 E","","50 54.5457N","1 20.2047W","",
+"SN120607","Hinkler Rd os 361 SE","","50 54.4816N","1 20.0461W","",
+"SN120608","Hinkler Rd os Hinkler ph SE","","50 54.4632N","1 20.0224W","",
+"SN120609","Warburton Rd os 2-28 NE","","50 54.4094N","1 19.9660W","",
+"SN120614","Hinkler Rd opp 202-222 SW","","50 54.4584N","1 19.7486W","",
+"SN120615","Hinkler Rd os 202-222 NE","","50 54.4664N","1 19.7425W","",
+"SN120622","Queensway opp Debenhams N","","50 54.1247N","1 24.0616W","",
+"SN120623","Queensway os Debenhams S","","50 54.1370N","1 24.0486W","",
+"SN120627","Queensway opp McCluskys N","","50 53.9117N","1 24.0916W","",
+"SN120632","Queensway os McCluskys S","","50 53.8982N","1 24.0841W","",
+"SN120635","Platform Rd os Admiralty House W","","50 53.8128N","1 23.9572W","",
+"SN120643","Kingsway os Kingsland Ct N","","50 54.3336N","1 23.8754W","",
+"SN120652","Itchen Bridge nr Albert Rd North E","","50 53.9295N","1 23.4634W","",
+"SN120653","Saltmarsh Rd nr Air Museum SW","","50 53.9034N","1 23.5354W","",
+"SN120654","Bridge Rd os 91 NE","","50 54.1029N","1 22.6019W","",
+"SN120655","Bridge Rd os 58 SW","","50 54.1196N","1 22.5829W","",
+"SN120656","Bridge Rd os 5 SW","","50 53.9770N","1 22.6573W","",
+"SN120657","Bridge Rd opp 7 NE","","50 53.9706N","1 22.6685W","",
+"SN120659","Woolston Link N","","50 53.8954N","1 22.6405W","",
+"SN120660","Portsmouth Rd opp 26 E","","50 53.8844N","1 22.7029W","",
+"SN120661","Portsmouth Rd os 26 W","","50 53.8780N","1 22.7030W","",
+"SN120662","Radstock Rd opp 34 E","","50 53.9947N","1 22.4318W","",
+"SN120664","Portsmouth Rd opp 60 SE","","50 53.8524N","1 22.3570W","",
+"SN120665","Portsmouth Rd os Woolston Library W","","50 53.8698N","1 22.4984W","",
+"SN120666","Bishops Rd opp 30 NE","","50 54.0445N","1 22.2665W","",
+"SN120667","Bishops Rd nr Radstock Rd SW","","50 53.9977N","1 22.2953W","",
+"SN120668","Bishops Rd os 61 NE","","50 54.1291N","1 22.1459W","",
+"SN120669","Wodehouse Rd opp 15 NW","","50 54.1369N","1 22.0886W","",
+"SN120670","Knighton Rd opp 10 N","","50 54.2569N","1 21.9308W","",
+"SN120671","Wodehouse Rd os 35 SE","","50 54.1052N","1 22.0250W","",
+"SN120672","Knighton Rd os 72 SW","","50 54.1082N","1 21.9798W","",
+"SN120673","Sholing Rd os 124 W","","50 54.2778N","1 21.9024W","",
+"SN120674","Sholing Rd nr Spring Rd E","","50 54.2797N","1 21.7599W","",
+"SN120675","Spring Rd os 1 Southeast Rd SW","","50 54.2860N","1 21.7265W","",
+"SN120676","Station Rd os 41 NE","","50 53.8260N","1 21.8744W","",
+"SN120677","Station Rd os 69 NE","","50 53.8469N","1 21.7402W","",
+"SN120678","Station Rd os 54 SW","","50 53.8323N","1 21.8334W","",
+"SN120682","South East Rd os 82 NW","","50 54.1174N","1 21.3790W","",
+"SN120684","Kathleen Rd opp Botany Bay Green NE","","50 54.0506N","1 21.2160W","",
+"SN120686","South East Rd os 130 NW","","50 54.0390N","1 21.2623W","",
+"SN120687","Kathleen Rd os 34 SW","","50 54.0060N","1 21.2516W","",
+"SN120689","Kathleen Rd opp St Monica Infant Sch NE","","50 53.9465N","1 21.4069W","",
+"SN120690","Kathleen Rd os St Monica Infant Sch SW","","50 53.9394N","1 21.4019W","",
+"SN120692","Kathleen Rd os 90 SW","","50 54.1431N","1 21.0603W","",
+"SN120693","Kathleen Rd os 157 NE","","50 54.2376N","1 20.8815W","",
+"SN120694","Kathleen Rd os 146 SW","","50 54.2237N","1 20.8988W","",
+"SN120695","Butts Rd opp 84 NE","","50 53.8831N","1 20.9829W","",
+"SN120696","Butts Rd os Bullseye ph SW","","50 53.9260N","1 20.9174W","",
+"SN120697","Butts Rd os 265 NE","","50 54.0080N","1 20.8190W","",
+"SN120698","Kathleen Rd os 198 NE","","50 54.2995N","1 20.7578W","",
+"SN120699","Kathleen Rd os 212 SW","","50 54.3149N","1 20.7175W","",
+"SN120700","Bursledon Rd os path to Linacre Rd SE","","50 54.3134N","1 20.3454W","",
+"SN120701","Bursledon Rd opp The Range NE","","50 54.3179N","1 20.3846W","",
+"SN120703","Orpen Rd nr Bursledon Rd SW","","50 54.1991N","1 20.1738W","",
+"SN120704","Butts Rd os 389 NE","","50 54.1627N","1 20.4184W","",
+"SN120705","Butts Rd os 388 SW","","50 54.1441N","1 20.4613W","",
+"SN120706","Butts Rd os 1 Ln ndseer Rd SW","","50 54.0571N","1 20.7219W","",
+"SN120707","Warburton Rd os Dumbleton Towers SE","","50 54.2651N","1 19.9211W","",
+"SN120708","Warburton Rd opp Dumbleton Towers NW","","50 54.2750N","1 19.9517W","",
+"SN120709","Warburton Rd opp Tatwin Cres S","","50 54.3938N","1 19.9654W","",
+"SN120710","Portsmouth Rd os Woolston sch SW","","50 53.7801N","1 22.0730W","",
+"SN120711","Victoria Rd os health centre N","","50 53.8243N","1 22.8590W","",
+"SN120712","Victoria Rd opp Keswick Rd SW","","50 53.7917N","1 22.8091W","",
+"SN120713","Victoria Rd os shipyard N","","50 53.7535N","1 22.8318W","",
+"SN120717","Weston Grove Rd os 5 SE","","50 53.6271N","1 22.8028W","",
+"SN120718","Weston Gro Rd os St Marks ch NE","","50 53.5909N","1 22.7060W","",
+"SN120719","Weston Grove Rd os 41 SE","","50 53.5750N","1 22.6524W","",
+"SN120726","Portsmouth Rd opp Woolston sch NE","","50 53.7786N","1 22.0918W","",
+"SN120729","Portsmouth Rd os Swan ph SE","","50 53.7392N","1 21.7792W","",
+"SN120730","Portsmouth Rd opp 211 NW","","50 53.7382N","1 21.7980W","",
+"SN120731","Wrights Hill nr Weston Ln SE","","50 53.6516N","1 21.5466W","",
+"SN120732","Wrights Hill opp 22-24 NW","","50 53.6533N","1 21.5790W","",
+"SN120733","Weston Ln opp 236 NE","","50 53.6322N","1 21.5571W","",
+"SN120734","Weston Ln os 226 SW","","50 53.6118N","1 21.5736W","",
+"SN120735","Upper Weston Ln os 275 NE","","50 53.6827N","1 21.3201W","",
+"SN120736","Upper Weston Ln os 272 SW","","50 53.6737N","1 21.3501W","",
+"SN120737","Newtown Rd os 70 SE","","50 53.5545N","1 21.3560W","",
+"SN120738","Newtown Rd opp 74 NW","","50 53.5469N","1 21.3518W","",
+"SN120739","Butts Rd nr 43 NE","","50 53.7616N","1 21.1450W","",
+"SN120740","Butts Rd opp 17 SW","","50 53.7160N","1 21.1934W","",
+"SN120741","Newtown Rd os 152 SE","","50 53.4376N","1 21.2006W","",
+"SN120742","Newtown Rd opp 146 NW","","50 53.4512N","1 21.2167W","",
+"SN120743","Weston Ln opp 134 NE","","50 53.4481N","1 21.8258W","",
+"SN120744","Weston Ln os Leisure Centre SW","","50 53.4560N","1 21.7916W","",
+"SN120747","Weston Ln os 61 NE","","50 53.3686N","1 22.0973W","",
+"SN120748","Weston Ln opp 23A SW","","50 53.3137N","1 22.2251W","",
+"SN120751","Kingsclere Ave opp 7 NE","","50 53.3224N","1 22.0271W","",
+"SN120752","Wallace Rd os Kipling Ct SE","","50 53.3355N","1 21.9664W","",
+"SN120753","Kingsclere Ave os 96 SE","","50 53.2023N","1 22.0774W","",
+"SN120754","Kingsclere Ave nr Poulner Close SE","","50 53.2753N","1 21.7011W","",
+"SN120755","Kingsclere Ave os 220 SW","","50 53.2327N","1 21.6078W","",
+"SN120756","Kingsclere Ave nr Drayton Ct SW","","50 53.1576N","1 21.6873W","",
+"SN120757","Kingsclere Ave opp 169 SW","","50 53.1225N","1 21.7927W","",
+"SN120758","Tickleford Dr opp 99-103 NE","","50 53.2152N","1 21.4665W","",
+"SN120764","Station Rd opp Squirrel Dr SW","","50 53.8505N","1 21.6224W","",
+"SN120766","Kingsway os market S","","50 54.2827N","1 23.8445W","",
+"SN120769","Redbridge Ln nr Romsey Rd SW","","50 56.5860N","1 27.5784W","",
+"SN120774","Forest Hills Dr opp 84 E","","50 56.0703N","1 21.9335W","",
+"SN120775","Forest Hills Dr opp 12 NE","","50 56.0125N","1 22.2092W","",
+"SN120778","Thornhill Pk Rd os Baptist ch E","","50 54.8886N","1 20.0718W","",
+"SN120779","Thornhill Pk Rd os 74 W","","50 54.8813N","1 20.1069W","",
+"SN120780","Thornhill Pk Rd opp 15 W","","50 54.8728N","1 20.3213W","",
+"SN120788","Winn Rd os Sovereign Ct NE","","50 55.4171N","1 24.2131W","",
+"SN120789","Thornhill Pk Rd opp The Bitterne ph E","","50 54.8784N","1 20.2674W","",
+"SN120790","Bitterne Rd opp 645 W","","50 54.8738N","1 20.7045W","",
+"SN120791","Mansbridge Rd os 1 Monks Way NW","","50 56.4640N","1 22.2953W","",
+"SN120792","Bitterne Rd os 643 E","","50 54.8789N","1 20.7317W","",
+"SN120793","Mansbridge Rd opp Howard Cl NW","","50 56.4413N","1 22.1752W","",
+"SN120795","Mansbridge Rd nr Itchenside Cl S","","50 56.3359N","1 21.9469W","",
+"SN120797","Mansbridge Rd opp White Swan ph W","","50 56.2455N","1 21.7005W","",
+"SN120806","Botley Rd opp 39 SW","","50 53.6992N","1 20.7005W","",
+"SN120814","Sullivan Rd opp 12 SE","","50 54.0707N","1 20.3591W","",
+"SN120818","Montague Ave nr Montague Cl SE","","50 54.0026N","1 20.1553W","",
+"SN120819","Montague Ave opp Montague Cl NW","","50 53.9939N","1 20.1366W","",
+"SN120820","Botley Rd nr Montague Ave NE","","50 53.8722N","1 20.0863W","",
+"SN120821","Botley Rd opp 197 SW","","50 53.8906N","1 20.0024W","",
+"SN120822","Botley Rd nr Delius Ave NE","","50 53.8272N","1 20.2499W","",
+"SN120823","Botley Rd opp 153 SW","","50 53.8377N","1 20.1977W","",
+"SN120824","Botley Rd os Valentine Infant sch NE","","50 53.7691N","1 20.4606W","",
+"SN120825","Botley Rd opp Valentine Infant sch SW","","50 53.7658N","1 20.4581W","",
+"SN120826","Botley Rd opp 10 NE","","50 53.6702N","1 20.8212W","",
+"SN120827","Portsmouth Rd os 442-446 NW","","50 53.6532N","1 20.9579W","",
+"SN120828","Sullivan Rd opp Purcell Rd NW","","50 54.0480N","1 20.3577W","",
+"SN120829","Portsmouth Rd os 382 NW","","50 53.6873N","1 21.1793W","",
+"SN120838","Redbridge Rd os Redbridge Primary sch SE","","50 55.2701N","1 27.9445W","",
+"SN120839","Redbridge Rd os 50 SE","","50 55.1550N","1 27.6769W","",
+"SN120840","Redbridge Rd os MacDonalds SE","","50 55.0719N","1 27.4483W","",
+"SN120841","Redbridge Rd nr First Ave NW","","50 55.0718N","1 27.5259W","",
+"SN120842","Redbridge Rd opp 62 SE","","50 55.1607N","1 27.7392W","",
+"SN120843","Redbridge Rd nr Redbridge roundabout NW","","50 55.3017N","1 28.1293W","",
+"SN120844","Portsmouth Rd opp 382 SE","","50 53.6932N","1 21.1775W","",
+"SN120870","Bitterne Rd West os 203 SE","","50 55.0187N","1 22.2312W","",
+"SN120871","Bitterne Rd opp 362 SE","","50 54.9136N","1 21.8468W","",
+"SN120872","Radstock Rd opp 1 W","","50 53.9955N","1 22.5922W","",
+"SN120880","Peartree Ave os Peartree ch SW","","50 54.2577N","1 22.4846W","",
+"SN120881","Brunswick Pl opp 21 SE","","50 54.6447N","1 24.1411W","",
+"SN120891","Carlton Rd opp 2 S","","50 54.8697N","1 24.3704W","",
+"SN120898","St James Rd opp 106 NW","","50 55.4482N","1 25.5615W","",
+"SN120899","Houndwell Pl os Debenhams E","","50 54.1697N","1 24.0115W","",
+"SN120900","Glen Eyre Rd os 10 NW","","50 56.3224N","1 23.9923W","",
+"SN120906","Radstock Rd opp 47 W","","50 53.9819N","1 22.3612W","",
+"SN120912","Butts Rd os 64-70 SW","","50 53.8563N","1 21.0080W","",
+"SN120913","East Park Ter os tennis courts N","","50 54.4810N","1 24.0997W","",
+"SN120914","East Park Ter os Millais Gallery S","","50 54.5127N","1 24.0907W","",
+"SN120915","St Marys Rd os Sports Hall S","","50 54.6357N","1 23.9662W","",
+"SN120928","King Georges Ave os 221 SW","","50 55.2858N","1 26.6937W","",
+"SN120950","Hill Ln os Byron Ct S","","50 54.6708N","1 24.9310W","",
+"SN120951","Hill Ln os 52 N","","50 54.7102N","1 24.9434W","",
+"SN120953","Mansel Rd West os Holy Family sch NW","","50 55.9210N","1 27.9959W","",
+"SN120954","Mansel Rd West os 278 SE","","50 55.9237N","1 27.9908W","",
+"SN120961","North East Rd opp High Firs Rd NE","","50 54.4523N","1 20.8734W","",
+"SN120962","North East Rd opp 225 SW","","50 54.4683N","1 20.8348W","",
+"SN120963","North East Rd opp 151 SW","","50 54.3674N","1 21.0350W","",
+"SN120964","North East Rd os 18 SW","","50 54.1581N","1 21.3408W","",
+"SN120965","North East Rd opp 65 SW","","50 54.2332N","1 21.2502W","",
+"SN120966","North East Rd os 69 NE","","50 54.2439N","1 21.2432W","",
+"SN120967","North East Rd opp 166 NE","","50 54.3931N","1 20.9946W","",
+"SN120979","Coxford Rd os Princess Anne Hospital NE","","50 56.0899N","1 26.0540W","",
+"SN120980","Houndwell Pl opp Debenhams SE","","50 54.1679N","1 23.9791W","",
+"SN120981","Olive Rd opp 64 NW","","50 56.2478N","1 26.5747W","",
+"SN120983","Olive Rd os 62 SE","","50 56.2461N","1 26.5593W","",
+"SN120985","Coxford Rd os 114 SW","","50 56.0268N","1 26.3972W","",
+"SN120986","Coxford Rd os 129 NE","","50 56.0338N","1 26.3740W","",
+"SN120988","Coxford Rd nr Birch Rd E","","50 55.9978N","1 26.6426W","",
+"SN120989","Coxford Rd nr Birch Rd W","","50 55.9919N","1 26.6443W","",
+"SN120998","Wide Ln opp Ford works NE","","50 56.7189N","1 22.1305W","",
+"SN120999","Wide Ln os Ford works SW","","50 56.6760N","1 22.1720W","",
+"SN120P03","Landguard Rd os 28 SW - HR","","50 54.7536N","1 25.0896W","",
+"SN120P04","Arthur Rd os 10 S - HR","","50 54.7978N","1 25.1992W","",
+"SN120P05","Suffolk Ave os 72 E - HR","","50 54.8895N","1 25.2885W","",
+"SN120P06","Paynes Rd opp 6 NE - HR","","50 54.8351N","1 25.4334W","",
+"SN120P07","Park Rd os 111 SE - HR","","50 54.8252N","1 25.5009W","",
+"SN120P08","Richmond Rd os 49 NE - HR","","50 54.7957N","1 25.7599W","",
+"SN120P09","Foundry Ln os 174 SE - HR","","50 54.9612N","1 25.9482W","",
+"SN120P10","English Rd nr Imperial Ave SW - HR","","50 55.0963N","1 26.1011W","",
+"SN120P11","Dale Valley Rd os 73 SW - HR","","50 56.0234N","1 25.6894W","",
+"SN120P12","Coxford Rd os 8 NE - HR","","50 56.5550N","1 25.4958W","",
+"SN120P13","Dunvegan Dr nr Balmoral Cl SW - HR","","50 56.7597N","1 25.7657W","",
+"SN120P14","Sandpiper Rd opp Winchat Cl SW - HR","","50 56.8484N","1 26.2472W","",
+"SN121003","Bargate St nr Castle Way 2 W","","50 54.1637N","1 24.3145W","",
+"SN121005","Bassett Ave opp 205 SW","","50 56.8878N","1 24.2951W","",
+"SN121006","Bassett Ave nr Ridgemount Ave NE","","50 56.7429N","1 24.3422W","",
+"SN121007","Bassett Ave opp 122 NE","","50 56.5721N","1 24.3854W","",
+"SN121008","Bassett Ave nr Saxholm Way NE","","50 56.9509N","1 24.2900W","",
+"SN121009","Bassett Ave opp 243 SW","","50 56.9940N","1 24.2690W","",
+"SN121010","Bassett Ave nr Ridgemount Ave SW","","50 56.7332N","1 24.3338W","",
+"SN121014","Bursledon Rd nr Botley Rd SE","","50 54.0121N","1 19.7413W","",
+"SN121015","Bursledon Rd nr Botley Rd NW","","50 54.0084N","1 19.7465W","",
+"SN121020","Kingsclere Ave nr Hurstbourne Pl NW","","50 53.1153N","1 21.9515W","",
+"SN121021","Hanover Bldgs os Echo Shop E","","50 54.1858N","1 24.2050W","",
+"SN121022","Havelock Rd os BBC NW","","50 54.4878N","1 24.4930W","",
+"SN121025","Millbrook Rd nr Regents Park Rd E","","50 54.8167N","1 26.6387W","",
+"SN121026","Millbrook Rd nr King George Ave SE","","50 54.8445N","1 26.9243W","",
+"SN121027","Millbrook Rd os Brazier estate NW","","50 54.8410N","1 26.9824W","",
+"SN121031","Portland Ter os Marlands S","","50 54.3378N","1 24.3788W","",
+"SN121033","Portsmouth Rd opp Veal store SE","","50 53.5763N","1 20.6254W","",
+"SN121034","Portsmouth Rd os 459 SE","","50 53.6276N","1 20.8303W","",
+"SN121035","Portsmouth Rd os Picador car dealer NW","","50 53.5841N","1 20.6740W","",
+"SN121036","Redbridge Hill os 94 W","","50 55.5979N","1 26.8565W","",
+"SN121037","Redbridge Hill opp 54 E","","50 55.5978N","1 26.7225W","",
+"SN121038","Redbridge Hill opp Walnut Grove E","","50 55.6084N","1 26.9085W","",
+"SN121039","Redbridge Hill opp Holy Family ch W","","50 55.6053N","1 27.0357W","",
+"SN121040","Redbridge Hill os 42 W","","50 55.5890N","1 26.6807W","",
+"SN121041","Redbridge Hill os Holy Family ch E","","50 55.6111N","1 27.0100W","",
+"SN121042","Romsey Rd nr Redbridge Ln SE","","50 56.5810N","1 27.5511W","",
+"SN121043","Romsey Rd nr path to Viking Cl SE","","50 56.4856N","1 27.4583W","",
+"SN121044","Romsey Rd opp 503 NW","","50 56.0966N","1 27.1102W","",
+"SN121045","Romsey Rd opp 425 NW","","50 55.8912N","1 26.9188W","",
+"SN121046","Romsey Rd os 533 SE","","50 56.1670N","1 27.1657W","",
+"SN121047","Stoneham Ln nr Channels Farm Rd NE","","50 56.7282N","1 22.6658W","",
+"SN121048","Stoneham Ln os 20 S","","50 56.5548N","1 22.8193W","",
+"SN121049","Stoneham Ln os 29 N","","50 56.5543N","1 22.8287W","",
+"SN121050","Stoneham Ln os 42 SW","","50 56.6300N","1 22.7534W","",
+"SN121051","Stoneham Ln nr Channels Farm Rd SW","","50 56.7255N","1 22.6590W","",
+"SN121052","The Avenue nr Oakmount Ave N","","50 55.6255N","1 24.3419W","",
+"SN121053","The Avenue nr Highfield Rd N","","50 55.7734N","1 24.3563W","",
+"SN121054","The Avenue nr Highfield Rd S","","50 55.7977N","1 24.3474W","",
+"SN121055","The Avenue nr Oakmount Ave S","","50 55.6427N","1 24.3349W","",
+"SN121059","Burgoyne Rd opp 1-11 E","","50 54.1800N","1 19.8439W","",
+"SN121060","Westend Rd opp 216 NE","","50 55.3202N","1 20.9185W","",
+"SN121061","West End Rd opp 157 SW","","50 55.2868N","1 21.2151W","",
+"SN121062","West End Rd os 218 SW","","50 55.3153N","1 20.9091W","",
+"SN121063","West End Rd os 159 NE","","50 55.2910N","1 21.2083W","",
+"SN121066","Wimpson Ln nr Cumbrian Way NE","","50 55.3365N","1 27.3632W","",
+"SN121067","Wimpson Ln opp 244-258 NE","","50 55.5907N","1 27.1443W","",
+"SN121068","Wimpson Ln os 179 NE","","50 55.4794N","1 27.2361W","",
+"SN121069","Bargate St nr Castle Way 1 W","","50 54.1620N","1 24.2992W","",
+"SN12151A","Burgess Rd os 469 NE","","50 56.3580N","1 22.8441W","",
+"SN122001","Tickleford Dr nr Staplehurst Cl NE","","50 53.2945N","1 21.2811W","",
+"SN122002","Newtown Rd opp Tenterton Ave NW","","50 53.3640N","1 21.1693W","",
+"SN122003","Newtown Rd nr Tickleford Dr SE","","50 53.3299N","1 21.1441W","",
+"SN122019","Rownhams Rd N nr Buchanan Rd SW","","50 56.7630N","1 27.0161W","",
+"SN12272A","Portswood Rd os 241 nr Somerfield NE","","50 55.5846N","1 23.5229W","",
+"SN12275A","Portswood Rd os 170 Superdrug SW","","50 55.5722N","1 23.5265W","",
+"SN122769","Redbridge Ln nr Toogoods Way NE","","50 56.5716N","1 27.6050W","",
+"SN12367A","Shirley High St os precinct 1 SE","","50 55.4211N","1 26.1040W","",
+"SN12367B","Shirley Rd nr MacDonald SE","","50 55.1339N","1 25.7378W","",
+"SN12368A","Shirley High St os 104A NE","","50 55.3930N","1 26.0838W","",
+"SN12368B","Shirley High St os Iceland NE","","50 55.4071N","1 26.1024W","",
+"SN12369A","Park St nr Carlisle Rd NE","","50 55.3492N","1 26.0750W","",
+"SN12369B","Park St nr Shirley High St NE","","50 55.3540N","1 26.0655W","",
+"SN12370A","Park St os 2 SW","","50 55.3481N","1 26.0656W","",
+"SN12426B","Bullar Rd Gyratory 1 SE","","50 55.1031N","1 22.4596W","",
+"SN12426C","Bullar Rd Gyratory 2 SE","","50 55.1002N","1 22.4366W","",
+"SN12441A","Commercial Rd os gallery 1 W","","50 54.5277N","1 24.3756W","",
+"SN12441B","Commercial Rd os gallery 2 W","","50 54.5295N","1 24.4063W","",
+"SN12493A","Waterloo Rd opp ch NW","","50 54.6749N","1 25.6632W","",
+"SN12518A","Wyndham Pl 2 N","","50 54.5065N","1 24.7795W","",
+"SN12524B","Above Bar St os Cenotaph N","","50 54.5710N","1 24.2905W","",
+"SN12524D","Above Bar St nr Cenotaph N","","50 54.5996N","1 24.2936W","",
+"SN12531A","Above Bar St os 101 N","","50 54.3707N","1 24.2735W","",
+"SN12531B","Above Bar St os 109 N","","50 54.3588N","1 24.2719W","",
+"SN12532A","Above Bar St os 85 N","","50 54.3443N","1 24.2712W","",
+"SN12532B","Above Bar St os 98 S","","50 54.3388N","1 24.2585W","",
+"SN12544A","New Rd opp Carronades NE","","50 54.4414N","1 23.9662W","",
+"SN12544B","New Rd opp Premier Inn NE","","50 54.4451N","1 23.9533W","",
+"SN12550B","Northam Rd opp 210 NE","","50 54.7410N","1 23.2778W","",
+"SN12550C","Northam Rd opp 214 NE","","50 54.7464N","1 23.2752W","",
+"SN12616B","Pound Tree Rd stand CC E","","50 54.3019N","1 24.1113W","",
+"SN12616C","Vincents Walk stand Ci S","","50 54.2341N","1 24.1557W","",
+"SN12616D","Pound Tree Rd stand CE W","","50 54.2922N","1 24.1081W","",
+"SN12616E","Pound Tree Rd stand CD E","","50 54.3023N","1 24.0866W","",
+"SN12617A","Pound Tree Rd stand CA E","","50 54.3021N","1 24.1583W","",
+"SN12617B","Above Bar St os 109 N","","50 54.3820N","1 24.2742W","",
+"SN12617C","Pound Tree Rd stand CF W","","50 54.2934N","1 24.1413W","",
+"SN12618A","Vincents Walk stand CG S","","50 54.2811N","1 24.1517W","",
+"SN12618B","Vincents Walk stand CH S","","50 54.2460N","1 24.1530W","",
+"SN12618C","Vincents Walk stand CL S","","50 54.2283N","1 24.1669W","",
+"SN12619A","Hanover Buildings stand CS S","","50 54.1852N","1 24.1879W","",
+"SN12619C","Sussex Pl stand CO os Laura Ashley N","","50 54.2721N","1 24.1954W","",
+"SN12619D","Vincents Walk stand CJ S","","50 54.2196N","1 24.1585W","",
+"SN12619E","Vincents Walk stand CK S","","50 54.2083N","1 24.1603W","",
+"SN12658A","Woolston Link 1 S","","50 53.8948N","1 22.6294W","",
+"SN12658B","Woolston Link 2 S","","50 53.8894N","1 22.6295W","",
+"SN12921A","West End Rd opp Sainsburys NE","","50 54.9073N","1 21.6881W","",
+"SN12921C","Bitterne Rd os 355 E","","50 54.8785N","1 21.7449W","",
+"SN12922A","West End Rd os Sainsburys 2 SW","","50 54.8965N","1 21.6849W","",
+"SNA09017","Waterloo Rd os Wellington Ct SE","","50 54.6249N","1 25.2542W","",
+"SNA09185","Portsmouth Rd opp 63 NW","","50 53.8382N","1 22.3290W","",
+"SNA09195","Hill Ln os King Edward School N","","50 55.3391N","1 24.9013W","",
+"SNA09196","Wyndham Pl 3 N","","50 54.5157N","1 24.7794W","",
+"SNA09197","Tremona Rd os 7 NE","","50 55.7298N","1 26.2138W","",
+"SNA09200","Anglesea Rd os No 20 NE","","50 55.4809N","1 26.0819W","",
+"SNA09201","Westwood Rd os 14 SW","","50 55.3393N","1 24.1825W","",
+"SNA09221","Landguard Rd os 23 NW - HR","","50 54.7470N","1 25.0658W","",
+"SNA09222","Arthur Rd os 31 N - HR","","50 54.8373N","1 25.2123W","",
+"SNA09223","Howard Rd nr Shirley Rd SW - HR","","50 54.8757N","1 25.3475W","",
+"SNA09224","Paynes Rd os 6 SW - HR","","50 54.8324N","1 25.4249W","",
+"SNA09225","Richmond Rd os 102 NW - HR","","50 54.8286N","1 25.5316W","",
+"SNA09226","Richmond Rd os 124 NW - HR","","50 54.8035N","1 25.9049W","",
+"SNA09227","Foundry Ln nr Nelson Rd N - HR","","50 54.8662N","1 25.9349W","",
+"SNA09228","Foundry Ln nr Heysham Rd NW - HR","","50 55.1034N","1 26.0079W","",
+"SNA09229","English Rd nr Imperial Ave SW - HR","","50 55.0972N","1 26.0712W","",
+"SNA09230","Waterhouse Way nr Waterhouse Way NW - HR","","50 55.0862N","1 26.2489W","",
+"SNA09231","Waterhouse Way nr 8 SE - HR","","50 55.0977N","1 26.2726W","",
+"SNA09233","Foundry Ln nr Heysham Rd SE - HR","","50 55.1045N","1 26.0002W","",
+"SNA09234","Foundry Ln nr Salcombe Rd SE - HR","","50 55.0044N","1 25.9588W","",
+"SNA09235","Foundry Ln nr Wolseley Rd S - HR","","50 54.8980N","1 25.9200W","",
+"SNA09236","Coxford Rd os 424 SW - HR","","50 56.4664N","1 25.5908W","",
+"SNA09237","Sandpiper Rd nr Puffin Cl NW - HR","","50 56.8018N","1 25.9753W","",
+"SNA09238","Sandpiper Rd nr Woburn Rd SE - HR","","50 56.6945N","1 25.9894W","",
+"SNA09239","Dunvegan Dr os 83 E - HR","","50 56.7706N","1 25.5555W","",
+"SNA09240","Dunvegan Dr nr Woburn Rd E - HR","","50 56.7572N","1 25.8990W","",
+"SNA09241","Sandpiper Rd os 137 SE - HR","","50 56.8647N","1 26.0514W","",
+"SNA09242","Sandpiper Rd opp 2 NW - HR","","50 56.6740N","1 26.3424W","",
+"SNA09285","Platform Rd os Portcullis House W","","50 53.8147N","1 23.9009W","",
+"SNA09298","Bassett Green Rd nr Bassett Green Cl SE","","50 56.7119N","1 23.4595W","",
+"SNA09299","Highfield Rd opp Omdurman Rd NE","","50 55.8481N","1 24.1829W","",
+"SNA09300","Glen Eyre Rd opp Chamberlain Hall SE","","50 56.5240N","1 24.1528W","",
+"SNA09313","Glen Eyre Rd nr Bassett Ave SE","","50 56.7680N","1 24.2889W","",
+"SNA09317","Northam Rd nr Britannia Rd NE","","50 54.5696N","1 23.4124W","",
+"SNA09318","Northam Rd nr Britannia Rd SW","","50 54.5642N","1 23.3979W","",
+"SNA09323","Romsey Rd opp 535 NW","","50 56.1578N","1 27.1649W","",
+"SNA09341","Portland Ter opp West Quay 1 SE","","50 54.2319N","1 24.3478W","",
+"SNA09343","Portland Ter os West Quay 2 NW","","50 54.2049N","1 24.3532W","",
+"SNA09388","Bassett Green Rd os 184 NW","","50 56.8397N","1 23.6526W","",
+"SNA09412","Tunstall Rd os Meredith Towers S","","50 54.2482N","1 19.7883W","",
+"SNA09436","Wilton Rd os No 177 NW","","50 55.3699N","1 25.2313W","",
+"SNA09437","Wilton Rd os No 170 SE","","50 55.3720N","1 25.2227W","",
+"SNA09438","Upper Shirley Ave os 121 SW","","50 55.5165N","1 25.4147W","",
+"SNA09450","Burgess Rd Opp 40b NE","","50 56.0873N","1 24.7476W","",
+"SNA09451","Burgess Rd nr 40b SW","","50 56.0856N","1 24.7340W","",
+"SNA09452","Wilton Rd nr South View Rd NW","","50 55.3111N","1 25.1253W","",
+"SNA09453","Wilton Rd nr South View Rd SE","","50 55.3171N","1 25.1261W","",
+"SNA09454","Wilton Rd os 121 NW","","50 55.5114N","1 25.3695W","",
+"SNA09464","Castle Way nr Bargate St SE","","50 54.1449N","1 24.3241W","",
+"SNA09572","Shirley Rd nr Nightingale Gr NW","","50 54.9537N","1 25.5173W","",
+"SNA09576","Weston Parade SE","","50 53.0884N","1 22.1719W","",
+"SNA09577","Weston Parade NW","","50 53.0809N","1 22.1805W","",
+"SNA09589","St Marys Rd opp Sports Hall N","","50 54.6368N","1 23.9756W","",
+"SNA09593","Mousehole Ln os 60A W","","50 55.2402N","1 21.8765W","",
+"SNA13670","Highfield Rd opp campus gate NE","","50 55.7162N","1 24.2503W","",
+"SNA13761","Town Quay pier opp Red Funnel NE","","50 53.6935N","1 24.3631W","",
+"SNA13762","Town Quay pier os Red Funnel SW","","50 53.6848N","1 24.3564W","",
+"SNA13766","Town Quay os Tower House E","","50 53.7735N","1 24.1872W","",
+"SNA13767","Town Quay opp Tower House W","","50 53.7633N","1 24.1950W","",
+"SNA13768","High St nr Town Quay N","","50 53.8364N","1 24.2513W","",
+"SNA13769","High St nr Town Quay S","","50 53.8472N","1 24.2434W","",
+"SNA19467","Warburton Rd opp St Colmans RC ch S","","50 54.1548N","1 19.8869W","",
+"SNA19469","Commercial St opp RC ch SW","","50 54.8884N","1 21.2830W","",
+"SNA19470","Shales Rd opp Balaclava Rd SW","","50 55.0853N","1 21.0890W","",
+"SNA19471","Taunton Dr opp Burnham Chase NW","","50 55.0193N","1 20.8621W","",
+"SNA19472","Midanbury Ln so Dalmally Gdns S","","50 55.3359N","1 22.1099W","",
+"SNA19473","Litchfield Rd opp 65 SW","","50 55.6807N","1 21.6195W","",
+"SNA19474","Middle Rd opp 11 SW","","50 53.8881N","1 21.6876W","",
+"SNA19476","Middle Rd os 112 SW","","50 54.1164N","1 21.6068W","",
+"SNA19477","Middle Rd os 216 SW","","50 54.3338N","1 21.4963W","",
+"SNA19478","Middle Rd os 270 SW","","50 54.4456N","1 21.4179W","",
+"SNA19479","Kathleen Rd os 253 NE","","50 54.3785N","1 20.6031W","",
+"SNA19482","General Hosp West Door","","50 56.0430N","1 26.1613W","",
+"SNA19483","Avon Rd os 35 SW","","50 55.4695N","1 21.9707W","",
+"SNA19495","Highfield Ave nr Highfield Rd SW","","50 55.9511N","1 24.1704W","",
+"SNA19559","Civic Centre Rd os stop AN Civic Ctr E","","50 54.4219N","1 24.3692W","",
+"SNA19692","Aldermoor Ave os Holly Oak Ct SW","","50 56.2723N","1 26.3823W","",
+"SNA19708","Spring Rd os 98 betting shop SE","","50 54.5649N","1 21.6297W","",
+"SNA19709","Central Station northern forecourt","","50 54.4701N","1 24.8243W","",
+"SNA19711","Spring Rd opp Freemantle Common SE","","50 54.7279N","1 21.8323W","",
+"SNA19712","Spring Rd os Freemantle Common NW","","50 54.7052N","1 21.8232W","",
+"SNA19721","Albert Rd North nr Anglesea Terrace S","","50 54.0686N","1 23.4573W","",
+"SNA19722","Albert Rd North nr Anglesea Terrace N","","50 54.0719N","1 23.4675W","",
+"SNA19739","Albert Rd North nr Itchen Br N","","50 53.9733N","1 23.4867W","",
+"SNA19771","Wakefield Rd 81 NE - HR","","50 55.6585N","1 21.5071W","",
+"SNA19772","Wakefield Rd opp Wakefield Ct NE - HR","","50 55.5150N","1 21.6055W","",
+"SNA19773","Glenfield Ave os 13 SW","","50 55.0087N","1 21.9633W","",
+"SNA19774","Upper Deacon Rd opp Caerleon Dr SW","","50 54.7235N","1 20.8397W","",
+"SNA19777","Univ Interchange SE","","50 56.1801N","1 23.8080W","",
+"SNA19780","Wessex Ln opp Montefiore Halls SW","","50 56.2417N","1 22.5980W","",
+"SNA40401","New Road South os East Park E","","50 54.4189N","1 24.2105W","",
+"SNA40402","London Rd os HSBC SW","","50 54.6599N","1 24.2757W","",
+"SNA40406","Tesco Millbrook inside grounds","","50 55.4017N","1 26.7854W","",
+"SNA40501","Rownhams Rd North nr Buchanan Rd NE","","50 56.7679N","1 27.0211W","",
+"SNA40502","Rownhams Rd N Sutherland Rd NW","","50 56.5945N","1 27.0872W","",
+"SNA40503","Rownhams Rd N Sutherland Rd SE","","50 56.5945N","1 27.0787W","",
+"SNA90772","Bedford Pl opp 14 NW","","50 54.7068N","1 24.3639W","",
+"SNA90773","Bedford Pl os 24 SE","","50 54.7392N","1 24.3797W","",
+"SNA90798","West End Rd os Sainsburys 1 SW","","50 54.9078N","1 21.6676W","",
+"SNA90808","Mansbridge Rd nr Itchenside Cl N","","50 56.3214N","1 21.9599W","",
+"SNA90830","Chapel Rd nr level crossing SE","","50 54.1397N","1 23.6313W","",
+"SNA90831","Chapel Rd opp ch NW","","50 54.1289N","1 23.7330W","",
+"SNA90867","William St os works SW","","50 54.5988N","1 23.0041W","",
+"SNA90868","Belvidere Rd nr Victoria St NE","","50 54.4374N","1 23.3074W","",
+"SNA90869","Belvidere Rd nr Victoria St SW","","50 54.4309N","1 23.3041W","",
+"SNA90870","Bedford Pl os 21 SE","","50 54.7224N","1 24.3697W","",
+"SNA90871","Millbank St os Forth House NE","","50 54.6097N","1 23.1234W","",
+"WIA04208","Salisbury bus station stand E","","51 4.2177N","1 47.6180W","",
+"WIA12274","Southampton Rd nr Clarendon Rd NW","","51 2.6910N","1 44.2329W","",
+"WIA12275","Southampton Rd nr Clarendon Rd SE","","51 2.6812N","1 44.1833W","",
+"WIA12283","Southampton Rd os Whaddon PO SE","","51 2.1298N","1 43.2546W","",
+"WIA12284","Southampton Rd opp PO Whaddon NW","","51 2.1347N","1 43.2717W","",
+"WIA12295","Common Rd nr The Street W","","51 0.6764N","1 39.0750W","",
+"WIA12339","Lyndhurst Rd nr New Rd NW","","50 57.6659N","1 37.9067W","",
+"WIA12340","Lyndhurst Rd nr New Rd SE","","50 57.6664N","1 37.8990W","",
+"WIA12348","Lyndhurst Rd nr A36 SE","","50 58.7611N","1 38.2407W","",
+"WIY42915","A31 Romsey Rd nr Barrow Hill Rd NE","","50 56.1611N","1 33.4041W","",
+"WIY42916","A31 Romsey Rd - Barrow Hill Rd SW","","50 56.1584N","1 33.3999W","",
+"WIY42982","Lyndhurst Rd nr Beech Grange SE","","50 58.0522N","1 38.0890W","",
+"WIY42983","Lyndhurst Rd nr Beech Grange NW","","50 58.0506N","1 38.0959W","",
+"haa13647","Castle Way nr Bargate St NW","","50 54.1493N","1 24.3377W","",
diff --git a/assets/data.db b/assets/data.db
new file mode 100644
index 0000000..b12d907
--- /dev/null
+++ b/assets/data.db
Binary files differ
diff --git a/assets/routes.csv b/assets/routes.csv
new file mode 100644
index 0000000..e16cf4b
--- /dev/null
+++ b/assets/routes.csv
@@ -0,0 +1,6 @@
+"id","code","label"
+326,U1,"NOC - Parkway - Eastleigh"
+468,U1N,"Leisure World - City Centre -"
+329,U2,"Civic Centre - Highfield Campus"
+327,U6,"Dock Gate 4 - General Hospital"
+354,U9,"Townhill Park - General Hospital"
diff --git a/assets/routestops.csv b/assets/routestops.csv
new file mode 100644
index 0000000..9edd2f4
--- /dev/null
+++ b/assets/routestops.csv
@@ -0,0 +1,328 @@
+"route-id","seq","stop-id"
+326,1,HAA13579
+326,2,SN120635
+326,3,SNA13767
+326,4,SNA13768
+326,5,HA120625
+326,6,SNA09343
+326,7,SN120553
+326,8,SN120520
+326,9,SN120527
+326,10,SN12524D
+326,11,SN120522
+326,12,SN120535
+326,13,SN120405
+326,14,SN120401
+326,15,SN120398
+326,16,SN120788
+326,17,SN120282
+326,18,SN120281
+326,19,SN120276
+326,20,SN12272A
+326,21,SN120268
+326,22,SN120267
+326,23,SN120257
+326,24,SNA19777
+326,25,SN120131
+326,26,SN120139
+326,27,SN120137
+326,28,SN120144
+326,29,HAA13379
+326,30,HAA13380
+326,31,SN120160
+326,32,HAA13650
+326,33,SN120162
+326,34,HAA13386
+326,35,SN120998
+326,36,HA030183
+326,37,HA030200
+326,38,HAA09425
+326,39,HA030198
+326,40,HA030203
+326,41,HA030204
+326,42,HA030206
+326,43,HA030212
+326,44,HA030212
+326,45,HA030207
+326,46,HA030205
+326,47,HA030202
+326,48,HA030199
+326,49,HAA09426
+326,50,HA030201
+326,51,HA030183
+326,52,HA030184
+326,53,HAA09424
+326,54,SN120999
+326,55,SN120164
+326,56,SN120163
+326,57,HAA13651
+326,58,SNA19780
+326,59,HAA13381
+326,60,SN120147
+326,61,SN120145
+326,62,SN120140
+326,63,SN120136
+326,64,SN120134
+326,65,HAA13668
+326,66,SN120256
+326,67,SN120266
+326,68,SN120269
+326,69,SN12275A
+326,70,SN120278
+326,71,SN120280
+326,72,SN120283
+326,73,SN120399
+326,74,SN120400
+326,75,SN120404
+326,76,SN120406
+326,77,SN120536
+326,78,SNA40402
+326,79,SN120525
+326,80,HAA13584
+326,81,SN120520
+326,82,SN121031
+326,83,HAA13583
+326,84,HA120626
+326,85,SNA13769
+326,86,SNA13766
+326,87,SNA09285
+326,88,MG1031
+468,1,HAA13649
+468,2,SNA13768
+468,3,HA120625
+468,4,haa13647
+468,5,SN120527
+468,6,SN12524D
+468,7,SN120522
+468,8,SN120539
+468,9,SN120537
+468,10,SN120409
+468,11,SN120413
+468,12,SN120279
+468,13,SN12272A
+468,14,SN120268
+468,15,SN120267
+468,16,SN120257
+468,17,SNA19777
+468,18,SN120131
+468,19,SN120139
+468,20,SN120137
+468,21,SN120144
+468,22,HAA13379
+468,23,HAA13380
+468,24,SN120160
+468,25,HAA13650
+468,26,SN120162
+468,27,HAA13386
+468,28,SN120998
+468,29,HA030183
+329,1,SN120527
+329,2,SN12524D
+329,3,SN120522
+329,4,SN120535
+329,5,SN120405
+329,6,SN120401
+329,7,SN120398
+329,8,SN121052
+329,9,SNA13670
+329,10,SNA09299
+329,11,SNA19495
+329,12,SN120121
+329,13,SN120127
+329,14,SN120134
+329,15,SNA19777
+329,16,SN120900
+329,17,SN120125
+329,18,SN120130
+329,19,SN120141
+329,20,SN120142
+329,21,SN120031
+329,22,SNA09298
+329,23,SNA09298
+329,24,SNA09388
+329,25,SN121009
+329,26,SN121005
+329,27,SNA09313
+329,28,SNA09300
+329,29,SN120124
+329,30,SN120126
+329,31,SN120134
+329,32,HAA13668
+329,33,SN120128
+329,34,SN120120
+329,35,SN121054
+329,36,SN121055
+329,37,SN120400
+329,38,SN120404
+329,39,SN120406
+329,40,SN120536
+329,41,SNA40402
+329,42,SN120526
+329,43,SN120527
+327,1,HAA13579
+327,2,SN120635
+327,3,SNA13767
+327,4,SNA13768
+327,5,HA120625
+327,6,SNA09343
+327,7,SN120553
+327,8,SN120527
+327,9,SNA40401
+327,10,SN120913
+327,11,SN120539
+327,12,SN120537
+327,13,SN120409
+327,14,SN120413
+327,15,SN120279
+327,16,SN12272A
+327,17,SN120284
+327,18,SN120289
+327,19,SN120159
+327,20,SN120157
+327,21,SN120153
+327,22,SN120150
+327,23,SN120163
+327,24,HAA13651
+327,25,SNA19780
+327,26,HAA13381
+327,27,SN120147
+327,28,SN120145
+327,29,SN120140
+327,30,SN120136
+327,31,SN120134
+327,32,SNA19777
+327,33,SN120128
+327,34,SN120120
+327,35,SN120118
+327,36,SN120117
+327,37,SN120114
+327,38,SN120113
+327,39,SN120098
+327,40,SN120233
+327,41,SN120231
+327,42,SN120225
+327,43,SN120221
+327,44,SNA19482
+327,45,SNA19482
+327,46,SN120979
+327,47,SN120084
+327,48,SN120222
+327,49,SN120223
+327,50,SN120224
+327,51,SN120228
+327,52,SN120232
+327,53,SN120097
+327,54,SN120112
+327,55,SN120111
+327,56,SN120115
+327,57,SN120119
+327,58,SN120121
+327,59,SN120127
+327,60,SN120134
+327,61,HAA13668
+327,62,SN120131
+327,63,SN120139
+327,64,SN120137
+327,65,SN120144
+327,66,SN120146
+327,67,SN12151A
+327,68,SN120163
+327,69,HAA13651
+327,70,SN120161
+327,71,HA120154
+327,72,SN120158
+327,73,SN120287
+327,74,SN120300
+327,75,SN120285
+327,76,SN12275A
+327,77,SN120415
+327,78,SN120412
+327,79,SN120411
+327,80,SN120410
+327,81,SN120538
+327,82,SN120540
+327,83,SN120914
+327,84,SN120533
+327,85,HAA13584
+327,86,SN121031
+327,87,HAA13583
+327,88,HA120626
+327,89,SNA13769
+327,90,SNA13766
+327,91,HA120633
+327,92,SNA09285
+327,93,MG1031
+354,1,SN120171
+354,2,SN120319
+354,3,HA120322
+354,4,HA120323
+354,5,SN120443
+354,6,SN120438
+354,7,SN120316
+354,8,SN120314
+354,9,SN120297
+354,10,SN120290
+354,11,SN120293
+354,12,SN120295
+354,13,SN120313
+354,14,SN120296
+354,15,SN120294
+354,16,SN120310
+354,17,HA120307
+354,18,HA120305
+354,19,HA120303
+354,20,SN120274
+354,21,SN120268
+354,22,SN120267
+354,23,SN120257
+354,24,SNA19777
+354,25,SN120128
+354,26,SN120120
+354,27,SNA09451
+354,28,SN120099
+354,29,SN120243
+354,30,SN120245
+354,31,SN120247
+354,32,SN120388
+354,33,SNA09452
+354,34,SNA09436
+354,35,SNA09454
+354,36,SN120236
+354,37,SN120230
+354,38,SN120225
+354,39,SN120221
+354,40,SN120082
+354,41,SN120084
+354,42,SN120222
+354,43,SN120223
+354,44,SN120224
+354,45,SN120228
+354,46,SN120235
+354,47,SN120237
+354,48,SNA09437
+354,49,SNA09453
+354,50,SNA09195
+354,51,SN120248
+354,52,SN120246
+354,53,SN120242
+354,54,SN120100
+354,55,SNA09450
+354,56,SN120121
+354,57,SN120127
+354,58,SN120134
+354,59,SNA19777
+354,60,SN120256
+354,61,SN120266
+354,62,SN120269
+354,63,SN120273
+354,64,SN120302
+354,65,HA120304
+354,66,HA120306
+354,67,SN120308
+354,68,SN120311
+354,69,SN120312
+354,70,SN120292
+354,71,SN120291
+354,72,SN120775
+354,73,SN120774
+354,74,SN120171
diff --git a/assets/sites.csv b/assets/sites.csv
new file mode 100644
index 0000000..878b401
--- /dev/null
+++ b/assets/sites.csv
@@ -0,0 +1,22 @@
+Id,Name,Long,Lat,Polygon,source
+1,Highfield Campus,,,"-1.3990823 50.9377130,-1.4006918 50.9342877,-1.3979531 50.9330237,-1.3961531 50.9328590,-1.3956357 50.9329379,-1.3954335 50.9331140,-1.3950459 50.9331990,-1.3951385 50.9333849,-1.3946835 50.9334752,-1.3944391 50.9334114,-1.3944644 50.9331512,-1.3939419 50.9330131,-1.3938408 50.9334699,-1.3928043 50.9349887,-1.3925852 50.9349356,-1.3924841 50.9351109,-1.3927200 50.9351640,-1.3923620 50.9357142,-1.3944239 50.9363169,-1.3945234 50.9365712,-1.3951385 50.9371501,-1.3938914 50.9370279,-1.3939167 50.9369164,-1.3936133 50.9368793,-1.3934026 50.9378988,-1.3935543 50.9379095,-1.3936049 50.9381643,-1.3990823 50.9377130",http://os.openstreetmap.org/
+2,Boldrewood Campus,-1.4046552,50.9372223,"-1.4034619 50.9368059,-1.4062591 50.9360660,-1.4064260 50.9376872,-1.4054058 50.9377964,-1.4046488 50.9379783,-1.4041933 50.9379096,-1.4038789 50.9380430,-1.4039815 50.9381360,-1.4037634 50.9382573,-1.4035709 50.9381360,-1.4031090 50.9381320,-1.4030577 50.9374204,-1.4033207 50.9373557,-1.4035389 50.9370363,-1.4034619 50.9368059",http://os.openstreetmap.org/
+3,Avenue Campus,-1.402511,50.928699,"-1.4033313 50.9296693,-1.4011463 50.9289554,-1.4021913 50.9277164,-1.4041790 50.9282737,-1.4033313 50.9296693",http://os.openstreetmap.org/
+4,Winchester School of Art,-1.30954,51.065765,"-1.3104990 51.0653919,-1.3091437 51.0651497,-1.3090241 51.0653251,-1.3086520 51.0651497,-1.3080940 51.0654169,-1.3093961 51.0663689,-1.3104193 51.0665693,-1.3111235 51.0658595,-1.3103661 51.0657009,-1.3104990 51.0653919",http://os.openstreetmap.org/
+5,The University of Southampton Science Park,-1.424618,50.962158,"-1.4200515 50.9655440,-1.4196262 50.9651958,-1.4211360 50.9642985,-1.4215825 50.9638565,-1.4214762 50.9629458,-1.4219441 50.9621556,-1.4223056 50.9607761,-1.4223268 50.9596912,-1.4257080 50.9601733,-1.4286638 50.9603609,-1.4336611 50.9602537,-1.4339588 50.9608296,-1.4332145 50.9610573,-1.4335547 50.9618208,-1.4317047 50.9619547,-1.4303863 50.9628655,-1.4290466 50.9619011,-1.4270477 50.9623699,-1.4290591 50.9643976,-1.4275013 50.9649480,-1.4248037 50.9641822,-1.4237090 50.9641512,-1.4225182 50.9647539,-1.4219015 50.9654101,-1.4211785 50.9656913,-1.4200515 50.9655440",http://os.openstreetmap.org/
+6,National Oceanography Centre Campus,-1.3946555,50.8927263,"-1.3963013 50.8937513,-1.3942781 50.8935386,-1.3933204 50.8934195,-1.3924032 50.8927474,-1.3922278 50.8921944,-1.3935902 50.8912840,-1.3963553 50.8925687,-1.3961530 50.8927134,-1.3967330 50.8930197,-1.3963013 50.8937513",http://os.openstreetmap.org/
+8,Boat House,,,"-1.3800720 50.9347696,-1.3797898 50.9344413,-1.3800286 50.9343866,-1.3802818 50.9341313,-1.3801805 50.9339352,-1.3799562 50.9337528,-1.3802022 50.9334929,-1.3810849 50.9337164,-1.3805061 50.9346875,-1.3800720 50.9347696",http://os.openstreetmap.org/
+18,Southampton General Hospital,,,"-1.4392547 50.9337565,-1.4392547 50.9332940,-1.4381754 50.9326954,-1.4384560 50.9325321,-1.4345488 50.9302464,-1.4317425 50.9323824,-1.4315698 50.9337429,-1.4339012 50.9348312,-1.4341602 50.9355931,-1.4348510 50.9361236,-1.4365564 50.9353482,-1.4357361 50.9342871,-1.4392547 50.9337565",http://os.openstreetmap.org/
+20,Royal South Hants Hospital,,,"-1.3980658 50.9135097,-1.3952237 50.9132480,-1.3955633 50.9117098,-1.3990719 50.9116384,-1.3990467 50.9126851,-1.3983677 50.9127168,-1.3980658 50.9135097",http://os.openstreetmap.org/
+39,Recreation Facilities at Wide Lane,,,"-1.3664622 50.9482380,-1.3647258 50.9494535,-1.3650860 50.9505474,-1.3647001 50.9509444,-1.3632810 50.9513658,-1.3626464 50.9517979,-1.3602112 50.9547041,-1.3641899 50.9548553,-1.3689403 50.9544880,-1.3680314 50.9529215,-1.3682886 50.9492590,-1.3664622 50.9482380",http://os.openstreetmap.org/
+45,Belgrave Industrial Site,-1.3840253,50.9309864,"-1.3841191 50.9303904,-1.3845444 50.9304838,-1.3839286 50.9315982,-1.3835033 50.9315048,-1.3841191 50.9303904"
+56,Highfield Hall,-1.402286,50.930084,"-1.4030286 50.9305226,-1.4014071 50.9299818,-1.4017779 50.9296106,-1.4032176 50.9301239,-1.4030286 50.9305226",http://os.openstreetmap.org/
+57,Glen Eyre Hall,-1.401615,50.943504,"-1.4016517 50.9418655,-1.4013481 50.9423883,-1.4011390 50.9423458,-1.3990076 50.9432298,-1.3990615 50.9439693,-1.3995269 50.9439608,-1.3999721 50.9440756,-1.4009299 50.9442286,-1.4017056 50.9443178,-1.4023532 50.9443476,-1.4026162 50.9443433,-1.4030614 50.9442243,-1.4035470 50.9439311,-1.4034863 50.9430811,-1.4033919 50.9428303,-1.4031626 50.9425668,-1.4027106 50.9422481,-1.4016517 50.9418655",http://os.openstreetmap.org/
+58,South Hill Hall,-1.402248,50.94146,"-1.4030801 50.9407406,-1.4032299 50.9407878,-1.4027057 50.9419262,-1.4018819 50.9416725,-1.4014232 50.9415428,-1.4012828 50.9413835,-1.4030801 50.9407406",http://os.openstreetmap.org/
+59,Chamberlain Hall,-1.403273,50.941608,"-1.4027057 50.9419262,-1.4032299 50.9422742,-1.4036418 50.9421090,-1.4039226 50.9413540,-1.4032299 50.9407878,-1.4027057 50.9419262",http://os.openstreetmap.org/
+60,Hartley Grove,-1.401696,50.940693,"-1.4012828 50.9413835,-1.4030801 50.9407406,-1.4021815 50.9398971,-1.4008429 50.9404220,-1.4012828 50.9413835",http://os.openstreetmap.org/
+62,Bencraft Hall,-1.390811,50.945885,"-1.3917348 50.9458870,-1.3908607 50.9464318,-1.3900583 50.9459207,-1.3909324 50.9453760,-1.3917348 50.9458870",http://os.openstreetmap.org/
+63,Connaught Hall,-1.374632,50.937965,"-1.3756787 50.9387817,-1.3757050 50.9376211,-1.3754814 50.9374885,-1.3750604 50.9370408,-1.3738765 50.9373973,-1.3743632 50.9387983,-1.3756787 50.9387817",http://os.openstreetmap.org/
+64,Montefiore Hall,-1.377164,50.938297,"-1.3789171 50.9373740,-1.3786071 50.9367713,-1.3783302 50.9367713,-1.3781653 50.9369750,-1.3778355 50.9371869,-1.3772750 50.9373490,-1.3760088 50.9376358,-1.3759626 50.9395765,-1.3768859 50.9396638,-1.3766683 50.9402373,-1.3770376 50.9403287,-1.3779213 50.9390778,-1.3789171 50.9373740",http://os.openstreetmap.org/
+65,Stoneham Hall,-1.3765588,50.9369483,"-1.3780071 50.9367009,-1.3776782 50.9369745,-1.3771652 50.9371569,-1.3759155 50.9374636,-1.3755866 50.9372564,-1.3754551 50.9369414,-1.3775730 50.9363445,-1.3780071 50.9367009",http://os.openstreetmap.org/
+70,Erasmus Park,-1.3000948,51.0687982,"-1.3005228 51.0677314,-1.3005750 51.0683404,-1.3004482 51.0688089,-1.2999040 51.0697038,-1.2994641 51.0696101,-1.2999561 51.0686450,-1.3000605 51.0683311,-1.3000531 51.0680125,-1.3005228 51.0677314" \ No newline at end of file
diff --git a/gen/net/cbaines/suma/R.java b/gen/net/cbaines/suma/R.java
new file mode 100644
index 0000000..cc16eab
--- /dev/null
+++ b/gen/net/cbaines/suma/R.java
@@ -0,0 +1,140 @@
+/* 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 net.cbaines.suma;
+
+public final class R {
+ public static final class array {
+ public static final int buildingTypes=0x7f070001;
+ public static final int preferencesHeadings=0x7f070003;
+ public static final int uniLinkBusRoutes=0x7f070000;
+ public static final int utilityOverlays=0x7f070002;
+ }
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int building=0x7f020000;
+ public static final int building_fav=0x7f020001;
+ public static final int busstop=0x7f020002;
+ public static final int busstop_fav=0x7f020003;
+ public static final int ic_menu_star=0x7f020004;
+ public static final int u1_back=0x7f020005;
+ public static final int u1n_back=0x7f020006;
+ public static final int u2_back=0x7f020007;
+ public static final int u6_back=0x7f020008;
+ public static final int u9_back=0x7f020009;
+ }
+ public static final class id {
+ public static final int busStopID=0x7f09000c;
+ public static final int busStopLoadBar=0x7f09000f;
+ public static final int busStopMessage=0x7f09000e;
+ public static final int busStopName=0x7f090004;
+ public static final int busStopTimes=0x7f090010;
+ public static final int busStopU1=0x7f090006;
+ public static final int busStopU1N=0x7f090007;
+ public static final int busStopU2=0x7f090008;
+ public static final int busStopU6=0x7f090009;
+ public static final int busStopU9=0x7f09000a;
+ public static final int busTimeContentLayout=0x7f09000d;
+ public static final int check1=0x7f090020;
+ public static final int childname=0x7f09001f;
+ public static final int donateBitcoinAddress=0x7f090017;
+ public static final int donateButton=0x7f090003;
+ public static final int donateDialogErrorMessage=0x7f090016;
+ public static final int donateDialogMessage=0x7f090013;
+ public static final int donateDialogMessageLayout=0x7f090015;
+ public static final int donateDialogProgress=0x7f090014;
+ public static final int favouriteCheckBox=0x7f09000b;
+ public static final int favouriteDialogMessage=0x7f090018;
+ public static final int favouriteListItems=0x7f090019;
+ public static final int findContentLayout=0x7f09001b;
+ public static final int findListItems=0x7f09001d;
+ public static final int findLoadBar=0x7f09001c;
+ public static final int helpExpandableListView=0x7f090002;
+ public static final int layout_root=0x7f090011;
+ public static final int linearLayout1=0x7f090005;
+ public static final int linearLayout2=0x7f090012;
+ public static final int mapview=0x7f09001e;
+ public static final int menu_about=0x7f090026;
+ public static final int menu_favourites=0x7f090027;
+ public static final int menu_find=0x7f090022;
+ public static final int menu_find_my_location=0x7f090024;
+ public static final int menu_preferences=0x7f090023;
+ public static final int menu_view=0x7f090025;
+ public static final int searchBar=0x7f09001a;
+ public static final int textView1=0x7f090000;
+ public static final int textView2=0x7f090001;
+ public static final int view_list=0x7f090021;
+ }
+ public static final class layout {
+ public static final int about_dialog=0x7f030000;
+ public static final int bustimes=0x7f030001;
+ public static final int donate_dialog=0x7f030002;
+ public static final int favourite_dialog=0x7f030003;
+ public static final int find=0x7f030004;
+ public static final int main=0x7f030005;
+ public static final int view_child_row=0x7f030006;
+ public static final int view_dialog=0x7f030007;
+ public static final int view_group_row=0x7f030008;
+ }
+ public static final class menu {
+ public static final int map_menu=0x7f080000;
+ }
+ public static final class raw {
+ public static final int u1=0x7f050000;
+ public static final int u1e=0x7f050001;
+ public static final int u1n=0x7f050002;
+ public static final int u2=0x7f050003;
+ public static final int u6=0x7f050004;
+ public static final int u9=0x7f050005;
+ }
+ public static final class string {
+ public static final int U1=0x7f060009;
+ public static final int U1N=0x7f06000a;
+ public static final int U2=0x7f06000b;
+ public static final int U6=0x7f06000c;
+ public static final int U9=0x7f06000d;
+ public static final int about_help_message=0x7f060015;
+ public static final int about_menu_instruction_text=0x7f060022;
+ public static final int app_name=0x7f060004;
+ public static final int bitcoin_error_message=0x7f06001a;
+ public static final int building_non_residential=0x7f060007;
+ public static final int building_residential=0x7f060006;
+ public static final int bustimes_favourite_checkbox_label=0x7f060023;
+ public static final int credits_help_message=0x7f060018;
+ public static final int donate_button=0x7f060019;
+ public static final int donate_dialog_error_title=0x7f060025;
+ public static final int donate_dialog_message=0x7f060024;
+ public static final int favourites_help_message=0x7f060016;
+ public static final int find_help_message=0x7f060011;
+ public static final int findmylocation_help_message=0x7f060013;
+ public static final int legal_message=0x7f060005;
+ public static final int licence_help_message=0x7f060017;
+ /** Preferences Messages
+ */
+ public static final int map_help_message=0x7f060010;
+ public static final int menu_about=0x7f06000e;
+ public static final int menu_favourites=0x7f06000f;
+ public static final int menu_find=0x7f060000;
+ public static final int menu_find_my_location=0x7f060003;
+ public static final int menu_preferences=0x7f060001;
+ public static final int menu_view=0x7f060002;
+ public static final int pref_bus_stop=0x7f060008;
+ public static final int preferences=0x7f06001b;
+ public static final int preferences_catagory_bus_times=0x7f06001f;
+ public static final int preferences_catagory_positioning=0x7f06001c;
+ public static final int preferences_gps_disabled=0x7f06001e;
+ public static final int preferences_gps_enabled=0x7f06001d;
+ public static final int preferences_help_message=0x7f060012;
+ public static final int preferences_live_bus_times_disabled=0x7f060021;
+ public static final int preferences_live_bus_times_enabled=0x7f060020;
+ public static final int view_help_message=0x7f060014;
+ }
+ public static final class xml {
+ public static final int preferences=0x7f040000;
+ }
+}
diff --git a/lint.xml b/lint.xml
new file mode 100644
index 0000000..ee0eead
--- /dev/null
+++ b/lint.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint> \ No newline at end of file
diff --git a/proguard.cfg b/proguard.cfg
new file mode 100644
index 0000000..b1cdf17
--- /dev/null
+++ b/proguard.cfg
@@ -0,0 +1,40 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/project.properties b/project.properties
new file mode 100644
index 0000000..5a70945
--- /dev/null
+++ b/project.properties
@@ -0,0 +1,11 @@
+# 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,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-7
diff --git a/res/drawable-hdpi/building.png b/res/drawable-hdpi/building.png
new file mode 100644
index 0000000..0e7b32e
--- /dev/null
+++ b/res/drawable-hdpi/building.png
Binary files differ
diff --git a/res/drawable-hdpi/building_fav.png b/res/drawable-hdpi/building_fav.png
new file mode 100644
index 0000000..82f1e83
--- /dev/null
+++ b/res/drawable-hdpi/building_fav.png
Binary files differ
diff --git a/res/drawable-hdpi/busstop.png b/res/drawable-hdpi/busstop.png
new file mode 100644
index 0000000..f0c7f42
--- /dev/null
+++ b/res/drawable-hdpi/busstop.png
Binary files differ
diff --git a/res/drawable-hdpi/busstop_fav.png b/res/drawable-hdpi/busstop_fav.png
new file mode 100644
index 0000000..a7b54b9
--- /dev/null
+++ b/res/drawable-hdpi/busstop_fav.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_star.png b/res/drawable-hdpi/ic_menu_star.png
new file mode 100644
index 0000000..4ab0b29
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_star.png
Binary files differ
diff --git a/res/drawable-ldpi/building.png b/res/drawable-ldpi/building.png
new file mode 100644
index 0000000..dba16a0
--- /dev/null
+++ b/res/drawable-ldpi/building.png
Binary files differ
diff --git a/res/drawable-ldpi/building_fav.png b/res/drawable-ldpi/building_fav.png
new file mode 100644
index 0000000..d3eb2eb
--- /dev/null
+++ b/res/drawable-ldpi/building_fav.png
Binary files differ
diff --git a/res/drawable-ldpi/busstop.png b/res/drawable-ldpi/busstop.png
new file mode 100644
index 0000000..31bbf38
--- /dev/null
+++ b/res/drawable-ldpi/busstop.png
Binary files differ
diff --git a/res/drawable-ldpi/busstop_fav.png b/res/drawable-ldpi/busstop_fav.png
new file mode 100644
index 0000000..67d3581
--- /dev/null
+++ b/res/drawable-ldpi/busstop_fav.png
Binary files differ
diff --git a/res/drawable-ldpi/ic_menu_star.png b/res/drawable-ldpi/ic_menu_star.png
new file mode 100644
index 0000000..318c900
--- /dev/null
+++ b/res/drawable-ldpi/ic_menu_star.png
Binary files differ
diff --git a/res/drawable-mdpi/building.png b/res/drawable-mdpi/building.png
new file mode 100644
index 0000000..15e22af
--- /dev/null
+++ b/res/drawable-mdpi/building.png
Binary files differ
diff --git a/res/drawable-mdpi/building_fav.png b/res/drawable-mdpi/building_fav.png
new file mode 100644
index 0000000..7f1d99b
--- /dev/null
+++ b/res/drawable-mdpi/building_fav.png
Binary files differ
diff --git a/res/drawable-mdpi/busstop.png b/res/drawable-mdpi/busstop.png
new file mode 100644
index 0000000..0b6c3ee
--- /dev/null
+++ b/res/drawable-mdpi/busstop.png
Binary files differ
diff --git a/res/drawable-mdpi/busstop_fav.png b/res/drawable-mdpi/busstop_fav.png
new file mode 100644
index 0000000..f5d4723
--- /dev/null
+++ b/res/drawable-mdpi/busstop_fav.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_star.png b/res/drawable-mdpi/ic_menu_star.png
new file mode 100644
index 0000000..8781250
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_star.png
Binary files differ
diff --git a/res/drawable-xhdpi/building.png b/res/drawable-xhdpi/building.png
new file mode 100644
index 0000000..55a14df
--- /dev/null
+++ b/res/drawable-xhdpi/building.png
Binary files differ
diff --git a/res/drawable-xhdpi/building_fav.png b/res/drawable-xhdpi/building_fav.png
new file mode 100644
index 0000000..e01d52d
--- /dev/null
+++ b/res/drawable-xhdpi/building_fav.png
Binary files differ
diff --git a/res/drawable-xhdpi/busstop.png b/res/drawable-xhdpi/busstop.png
new file mode 100644
index 0000000..5ad2209
--- /dev/null
+++ b/res/drawable-xhdpi/busstop.png
Binary files differ
diff --git a/res/drawable-xhdpi/busstop_fav.png b/res/drawable-xhdpi/busstop_fav.png
new file mode 100644
index 0000000..2e77006
--- /dev/null
+++ b/res/drawable-xhdpi/busstop_fav.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_star.png b/res/drawable-xhdpi/ic_menu_star.png
new file mode 100644
index 0000000..e82948a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_menu_star.png
Binary files differ
diff --git a/res/drawable/u1_back.xml b/res/drawable/u1_back.xml
new file mode 100644
index 0000000..d9f615b
--- /dev/null
+++ b/res/drawable/u1_back.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+
+ <solid android:color="#008BD0" >
+ </solid>
+
+ <corners
+ android:bottomLeftRadius="7dp"
+ android:bottomRightRadius="7dp"
+ android:topLeftRadius="7dp"
+ android:topRightRadius="7dp" />
+
+</shape> \ No newline at end of file
diff --git a/res/drawable/u1n_back.xml b/res/drawable/u1n_back.xml
new file mode 100644
index 0000000..3898629
--- /dev/null
+++ b/res/drawable/u1n_back.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+
+ <solid android:color="#002F6B" >
+ </solid>
+
+ <corners
+ android:bottomLeftRadius="7dp"
+ android:bottomRightRadius="7dp"
+ android:topLeftRadius="7dp"
+ android:topRightRadius="7dp" />
+
+</shape> \ No newline at end of file
diff --git a/res/drawable/u2_back.xml b/res/drawable/u2_back.xml
new file mode 100644
index 0000000..e1fa567
--- /dev/null
+++ b/res/drawable/u2_back.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+
+ <solid android:color="#E2001A" >
+ </solid>
+
+ <corners
+ android:bottomLeftRadius="7dp"
+ android:bottomRightRadius="7dp"
+ android:topLeftRadius="7dp"
+ android:topRightRadius="7dp" />
+
+</shape> \ No newline at end of file
diff --git a/res/drawable/u6_back.xml b/res/drawable/u6_back.xml
new file mode 100644
index 0000000..cd60db7
--- /dev/null
+++ b/res/drawable/u6_back.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+
+ <solid android:color="#F7A800" >
+ </solid>
+
+ <corners
+ android:bottomLeftRadius="7dp"
+ android:bottomRightRadius="7dp"
+ android:topLeftRadius="7dp"
+ android:topRightRadius="7dp" />
+
+</shape> \ No newline at end of file
diff --git a/res/drawable/u9_back.xml b/res/drawable/u9_back.xml
new file mode 100644
index 0000000..6216ebc
--- /dev/null
+++ b/res/drawable/u9_back.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+
+ <solid android:color="#E75294" >
+ </solid>
+
+ <corners
+ android:bottomLeftRadius="7dp"
+ android:bottomRightRadius="7dp"
+ android:topLeftRadius="7dp"
+ android:topRightRadius="7dp" />
+
+</shape> \ No newline at end of file
diff --git a/res/layout/about_dialog.xml b/res/layout/about_dialog.xml
new file mode 100644
index 0000000..03a68ad
--- /dev/null
+++ b/res/layout/about_dialog.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/textView1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/app_name"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <TextView
+ android:id="@+id/textView2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/about_menu_instruction_text" />
+
+ <ExpandableListView
+ android:id="@+id/helpExpandableListView"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="0.05" >
+ </ExpandableListView>
+
+ <Button
+ android:id="@+id/donateButton"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/donate_button" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/bustimes.xml b/res/layout/bustimes.xml
new file mode 100644
index 0000000..b076274
--- /dev/null
+++ b/res/layout/bustimes.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center|top"
+ android:orientation="vertical"
+ android:theme="@android:style/Theme.NoTitleBar" >
+
+ <TextView
+ android:id="@+id/busStopName"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/busStopU1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="3dp"
+ android:background="@drawable/u1_back"
+ android:paddingLeft="5dp"
+ android:paddingRight="5dp"
+ android:text="@string/U1"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#FFFFFF" />
+
+ <TextView
+ android:id="@+id/busStopU1N"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/u1n_back"
+ android:paddingLeft="5dp"
+ android:paddingRight="5dp"
+ android:text="@string/U1N"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#FFFFFF" />
+
+ <TextView
+ android:id="@+id/busStopU2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/u2_back"
+ android:paddingLeft="5dp"
+ android:paddingRight="5dp"
+ android:text="@string/U2"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#FFFFFF" />
+
+ <TextView
+ android:id="@+id/busStopU6"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/u6_back"
+ android:paddingLeft="5dp"
+ android:paddingRight="5dp"
+ android:text="@string/U6"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#FFFFFF" />
+
+ <TextView
+ android:id="@+id/busStopU9"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/u9_back"
+ android:paddingLeft="5dp"
+ android:paddingRight="5dp"
+ android:text="@string/U9"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#FFFFFF" />
+
+ <CheckBox
+ android:id="@+id/favouriteCheckBox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bustimes_favourite_checkbox_label" />
+
+ <TextView
+ android:id="@+id/busStopID"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="5dp"
+ android:paddingRight="5dp"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/busTimeContentLayout"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/busStopMessage"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text=""
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <ProgressBar
+ android:id="@+id/busStopLoadBar"
+ style="?android:attr/progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ListView
+ android:id="@+id/busStopTimes"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" >
+ </ListView>
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/donate_dialog.xml b/res/layout/donate_dialog.xml
new file mode 100644
index 0000000..ce44e31
--- /dev/null
+++ b/res/layout/donate_dialog.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/layout_root"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ android:padding="10dp" >
+
+ <LinearLayout
+ android:id="@+id/linearLayout2"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/donateDialogMessage"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dp"
+ android:text="@string/donate_dialog_message"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <ProgressBar
+ android:id="@+id/donateDialogProgress"
+ android:layout_width="24dp"
+ android:layout_height="24dp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/donateDialogMessageLayout"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ android:visibility="gone" >
+
+ <TextView
+ android:id="@+id/donateDialogErrorMessage"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/bitcoin_error_message"
+ android:visibility="gone" />
+
+ <TextView
+ android:id="@+id/donateBitcoinAddress"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone" />
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/favourite_dialog.xml b/res/layout/favourite_dialog.xml
new file mode 100644
index 0000000..44cb02a
--- /dev/null
+++ b/res/layout/favourite_dialog.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/layout_root"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ android:padding="10dp" >
+
+ <TextView
+ android:id="@+id/favouriteDialogMessage"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:visibility="gone" />
+
+ <ListView
+ android:id="@+id/favouriteListItems"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" >
+ </ListView>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/find.xml b/res/layout/find.xml
new file mode 100644
index 0000000..62a3000
--- /dev/null
+++ b/res/layout/find.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center|top"
+ android:orientation="vertical"
+ android:theme="@android:style/Theme.NoTitleBar" >
+
+ <EditText
+ android:id="@+id/searchBar"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:inputType="text" />
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/findContentLayout"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center"
+ android:orientation="vertical" >
+
+ <ProgressBar
+ android:id="@+id/findLoadBar"
+ style="?android:attr/progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ListView
+ android:id="@+id/findListItems"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" >
+ </ListView>
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/main.xml b/res/layout/main.xml
new file mode 100644
index 0000000..dff45bd
--- /dev/null
+++ b/res/layout/main.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ android:theme="@android:style/Theme.NoTitleBar">
+
+ <org.osmdroid.views.MapView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/mapview"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+ </org.osmdroid.views.MapView>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/view_child_row.xml b/res/layout/view_child_row.xml
new file mode 100644
index 0000000..d1ac7f3
--- /dev/null
+++ b/res/layout/view_child_row.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingRight="10dp" >
+
+ <TextView
+ android:id="@+id/childname"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:paddingLeft="50dp"
+ android:textSize="25dp" />
+
+ <CheckBox
+ android:id="@+id/check1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:gravity="right" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/view_dialog.xml b/res/layout/view_dialog.xml
new file mode 100644
index 0000000..c03d169
--- /dev/null
+++ b/res/layout/view_dialog.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/layout_root"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ android:padding="10dp" >
+
+ <ExpandableListView
+ android:id="@+id/view_list"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1" >
+ </ExpandableListView>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/view_group_row.xml b/res/layout/view_group_row.xml
new file mode 100644
index 0000000..7b5989a
--- /dev/null
+++ b/res/layout/view_group_row.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <TextView
+ android:id="@+id/childname"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="5dp"
+ android:paddingLeft="50dp"
+ android:paddingTop="5dp"
+ android:textSize="28dp" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/menu/map_menu.xml b/res/menu/map_menu.xml
new file mode 100644
index 0000000..0d61dcd
--- /dev/null
+++ b/res/menu/map_menu.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_find" android:icon="@android:drawable/ic_menu_search"
+ android:title="@string/menu_find" />
+ <item android:id="@+id/menu_preferences" android:icon="@android:drawable/ic_menu_preferences"
+ android:title="@string/menu_preferences" />
+ <item android:id="@+id/menu_find_my_location" android:icon="@android:drawable/ic_menu_mylocation"
+ android:title="@string/menu_find_my_location"></item>
+ <item android:id="@+id/menu_view" android:icon="@android:drawable/ic_menu_more"
+ android:title="@string/menu_view" />
+ <item android:id="@+id/menu_about" android:icon="@android:drawable/ic_menu_info_details"
+ android:title="@string/menu_about" />
+ <item android:id="@+id/menu_favourites" android:icon="@drawable/ic_menu_star"
+ android:title="@string/menu_favourites" />
+
+</menu> \ No newline at end of file
diff --git a/res/raw/u1.gpx b/res/raw/u1.gpx
new file mode 100644
index 0000000..f4a2959
--- /dev/null
+++ b/res/raw/u1.gpx
@@ -0,0 +1,824 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
+ <metadata>
+ <author>
+ <name>chrisb8</name>
+ </author>
+ <copyright author="chrisb8">
+ <year>2012</year>
+ <license>http://creativecommons.org/licenses/by-sa/2.5</license>
+ </copyright>
+ <bounds minlat="50.8931914" minlon="-1.413991" maxlat="50.9497096" maxlon="-1.3635693" />
+ </metadata>
+ <trk> <trkseg>
+ <trkpt lat="50.93856691501375" lon="-1.389858740861517">
+ </trkpt>
+ <trkpt lat="50.93829770313622" lon="-1.3933133998645506">
+ </trkpt>
+ <trkpt lat="50.9380033768819" lon="-1.396151129085249">
+ </trkpt>
+ <trkpt lat="50.93796383052481" lon="-1.396324414284073">
+ </trkpt>
+ <trkpt lat="50.93791132288222" lon="-1.3964217440316278">
+ </trkpt>
+ <trkpt lat="50.93785250111673" lon="-1.3964590979730969">
+ </trkpt>
+ <trkpt lat="50.93712178404442" lon="-1.3963332268107562">
+ </trkpt>
+ <trkpt lat="50.936201422954824" lon="-1.396160064289726">
+ </trkpt>
+ <trkpt lat="50.9357680650971" lon="-1.3961087544285358">
+ </trkpt>
+ <trkpt lat="50.93570316893787" lon="-1.3961064002644052">
+ </trkpt>
+ <trkpt lat="50.935700952173164" lon="-1.3961993745900345">
+ </trkpt>
+ <trkpt lat="50.93571913461656" lon="-1.3963627612144054">
+ </trkpt>
+ <trkpt lat="50.93576969547591" lon="-1.3964525658425073">
+ </trkpt>
+ <trkpt lat="50.936095888509975" lon="-1.3965407529305744">
+ </trkpt>
+ <trkpt lat="50.93645770484579" lon="-1.3971037606433754">
+ </trkpt>
+ <trkpt lat="50.937081388649375" lon="-1.3972344300370747">
+ </trkpt>
+ <trkpt lat="50.937145729185374" lon="-1.3963698642902762">
+ </trkpt>
+ <trkpt lat="50.937124712867764" lon="-1.39633407283396">
+ </trkpt>
+ <trkpt lat="50.936206862232616" lon="-1.3961557123661528">
+ </trkpt>
+ <trkpt lat="50.93576953859724" lon="-1.3961086792827877">
+ </trkpt>
+ <trkpt lat="50.93569676455895" lon="-1.3961063895608279">
+ </trkpt>
+ <trkpt lat="50.935627250833825" lon="-1.396108455327118">
+ </trkpt>
+ <trkpt lat="50.93519947303469" lon="-1.396292411360292">
+ </trkpt>
+ <trkpt lat="50.93477559352361" lon="-1.396421368354055">
+ </trkpt>
+ <trkpt lat="50.934456607922336" lon="-1.396370546613303">
+ </trkpt>
+ <trkpt lat="50.93419807819269" lon="-1.3962288213435992">
+ </trkpt>
+ <trkpt lat="50.93342795847578" lon="-1.395668855332914">
+ </trkpt>
+ <trkpt lat="50.93281964477835" lon="-1.3954484220424717">
+ </trkpt>
+ <trkpt lat="50.93225711373697" lon="-1.3952143420534144">
+ </trkpt>
+ <trkpt lat="50.93152032793576" lon="-1.3930214282403326">
+ </trkpt>
+ <trkpt lat="50.93102017401074" lon="-1.3907687654716505">
+ </trkpt>
+ <trkpt lat="50.93028106779059" lon="-1.3906350746609224">
+ </trkpt>
+ <trkpt lat="50.92974216150566" lon="-1.3906472154829332">
+ </trkpt>
+ <trkpt lat="50.9291117279423" lon="-1.3907890283493543">
+ </trkpt>
+ <trkpt lat="50.92843406088357" lon="-1.3910353335766759">
+ </trkpt>
+ <trkpt lat="50.92729043748489" lon="-1.3914797462164743">
+ </trkpt>
+ <trkpt lat="50.92703423577239" lon="-1.3910235718617874">
+ </trkpt>
+ <trkpt lat="50.92695713573826" lon="-1.3910269729269216">
+ </trkpt>
+ <trkpt lat="50.92688283545017" lon="-1.3911392748833868">
+ </trkpt>
+ <trkpt lat="50.92658218108263" lon="-1.3916231719991532">
+ </trkpt>
+ <trkpt lat="50.926212889318386" lon="-1.3922221028688149">
+ </trkpt>
+ <trkpt lat="50.92587372012931" lon="-1.3926565837962883">
+ </trkpt>
+ <trkpt lat="50.92517885807723" lon="-1.3934417219143522">
+ </trkpt>
+ <trkpt lat="50.92465298550046" lon="-1.3939697312571016">
+ </trkpt>
+ <trkpt lat="50.9253695398468" lon="-1.3961345989806133">
+ </trkpt>
+ <trkpt lat="50.92602455422342" lon="-1.3978819861860652">
+ </trkpt>
+ <trkpt lat="50.92449378350409" lon="-1.401397789316902">
+ </trkpt>
+ <trkpt lat="50.92344356316862" lon="-1.4037839726285297">
+ </trkpt>
+ <trkpt lat="50.9233035308449" lon="-1.4043133439198012">
+ </trkpt>
+ <trkpt lat="50.92323756388906" lon="-1.4052072269388687">
+ </trkpt>
+ <trkpt lat="50.921751691035716" lon="-1.40496040642905">
+ </trkpt>
+ <trkpt lat="50.92032084561698" lon="-1.4046061042592304">
+ </trkpt>
+ <trkpt lat="50.91897640643002" lon="-1.4039871097339114">
+ </trkpt>
+ <trkpt lat="50.91897640643002" lon="-1.403987109733912">
+ </trkpt>
+ <trkpt lat="50.918528559659556" lon="-1.4034937535440868">
+ </trkpt>
+ <trkpt lat="50.91833694137635" lon="-1.403343964844504">
+ </trkpt>
+ <trkpt lat="50.9175014388437" lon="-1.402923925575669">
+ </trkpt>
+ <trkpt lat="50.91567117561357" lon="-1.4021249608139206">
+ </trkpt>
+ <trkpt lat="50.914705676580375" lon="-1.4013214508182408">
+ </trkpt>
+ <trkpt lat="50.914497078478924" lon="-1.4012174671717414">
+ </trkpt>
+ <trkpt lat="50.91429372198327" lon="-1.4012599153504273">
+ </trkpt>
+ <trkpt lat="50.91418708767953" lon="-1.4013768148895578">
+ </trkpt>
+ <trkpt lat="50.91413167283375" lon="-1.4015329161247407">
+ </trkpt>
+ <trkpt lat="50.914115639532554" lon="-1.401694846639763">
+ </trkpt>
+ <trkpt lat="50.913960679067586" lon="-1.4017657445805582">
+ </trkpt>
+ <trkpt lat="50.913871278564635" lon="-1.4018177364038078">
+ </trkpt>
+ <trkpt lat="50.91361797620699" lon="-1.4021911322253295">
+ </trkpt>
+ <trkpt lat="50.91346375549287" lon="-1.4024572684145769">
+ </trkpt>
+ <trkpt lat="50.91251640583275" lon="-1.4032823755179396">
+ </trkpt>
+ <trkpt lat="50.91129637580309" lon="-1.4044124388352146">
+ </trkpt>
+ <trkpt lat="50.91076257200425" lon="-1.4048616649767744">
+ </trkpt>
+ <trkpt lat="50.91033267412033" lon="-1.4048215590450077">
+ </trkpt>
+ <trkpt lat="50.90692700681981" lon="-1.4045404753694941">
+ </trkpt>
+ <trkpt lat="50.906849476132564" lon="-1.4054647434355227">
+ </trkpt>
+ <trkpt lat="50.90684505064505" lon="-1.4057566959028616">
+ </trkpt>
+ <trkpt lat="50.906876914145705" lon="-1.4061272509575606">
+ </trkpt>
+ <trkpt lat="50.906864522786925" lon="-1.4063462153080646">
+ </trkpt>
+ <trkpt lat="50.90682532148036" lon="-1.4065565054392632">
+ </trkpt>
+ <trkpt lat="50.90679840203188" lon="-1.4072067017069418">
+ </trkpt>
+ <trkpt lat="50.906885399804466" lon="-1.4074543080862465">
+ </trkpt>
+ <trkpt lat="50.90690024116973" lon="-1.4076313697885376">
+ </trkpt>
+ <trkpt lat="50.90688352223062" lon="-1.4079594944268454">
+ </trkpt>
+ <trkpt lat="50.90691581260698" lon="-1.4083654467714017">
+ </trkpt>
+ <trkpt lat="50.906964294195724" lon="-1.409015988652688">
+ </trkpt>
+ <trkpt lat="50.90704359190335" lon="-1.4100406881024838">
+ </trkpt>
+ <trkpt lat="50.90712489313221" lon="-1.4110451849664145">
+ </trkpt>
+ <trkpt lat="50.90711696666335" lon="-1.4113320350660528">
+ </trkpt>
+ <trkpt lat="50.90709166800876" lon="-1.4115927924031044">
+ </trkpt>
+ <trkpt lat="50.90702561972103" lon="-1.4120009550035693">
+ </trkpt>
+ <trkpt lat="50.90697489740272" lon="-1.4123295051491622">
+ </trkpt>
+ <trkpt lat="50.906976552789565" lon="-1.4126722951883566">
+ </trkpt>
+ <trkpt lat="50.907073497883815" lon="-1.4127357962469873">
+ </trkpt>
+ <trkpt lat="50.907024731482444" lon="-1.4132908776248914">
+ </trkpt>
+ <trkpt lat="50.90704580649827" lon="-1.4139196915024033">
+ </trkpt>
+ <trkpt lat="50.90706752410642" lon="-1.4139760751669503">
+ </trkpt>
+ <trkpt lat="50.90710319785532" lon="-1.413990962780131">
+ </trkpt>
+ <trkpt lat="50.90713382349701" lon="-1.4139559482357504">
+ </trkpt>
+ <trkpt lat="50.90714951110256" lon="-1.413878809427503">
+ </trkpt>
+ <trkpt lat="50.90710988727699" lon="-1.4132805684868195">
+ </trkpt>
+ <trkpt lat="50.907164975032885" lon="-1.4127115961549985">
+ </trkpt>
+ <trkpt lat="50.9071918693193" lon="-1.4122896987932032">
+ </trkpt>
+ <trkpt lat="50.907128658041366" lon="-1.4120594370426744">
+ </trkpt>
+ <trkpt lat="50.90719957942614" lon="-1.4116228397768493">
+ </trkpt>
+ <trkpt lat="50.907221910292556" lon="-1.4112029030310096">
+ </trkpt>
+ <trkpt lat="50.90711175996243" lon="-1.409810414944839">
+ </trkpt>
+ <trkpt lat="50.9069712092691" lon="-1.4084052942999854">
+ </trkpt>
+ <trkpt lat="50.90695391435455" lon="-1.4081230524386652">
+ </trkpt>
+ <trkpt lat="50.90699679660348" lon="-1.4078397049264997">
+ </trkpt>
+ <trkpt lat="50.907080035434824" lon="-1.4076461659551502">
+ </trkpt>
+ <trkpt lat="50.90707671207547" lon="-1.4074879472886448">
+ </trkpt>
+ <trkpt lat="50.90704123238911" lon="-1.4073930765310778">
+ </trkpt>
+ <trkpt lat="50.90682680772049" lon="-1.407054128828438">
+ </trkpt>
+ <trkpt lat="50.90658264083608" lon="-1.4068304347198461">
+ </trkpt>
+ <trkpt lat="50.90609677991284" lon="-1.406549676964073">
+ </trkpt>
+ <trkpt lat="50.90524773060761" lon="-1.4063222704898768">
+ </trkpt>
+ <trkpt lat="50.904610823279086" lon="-1.4061711405303652">
+ </trkpt>
+ <trkpt lat="50.90318855760956" lon="-1.4058078443865356">
+ </trkpt>
+ <trkpt lat="50.902738790045305" lon="-1.4055892961589094">
+ </trkpt>
+ <trkpt lat="50.90238526257987" lon="-1.4054796908772962">
+ </trkpt>
+ <trkpt lat="50.90163972061398" lon="-1.4049600693627322">
+ </trkpt>
+ <trkpt lat="50.90115178605379" lon="-1.4047721669894442">
+ </trkpt>
+ <trkpt lat="50.900403718245826" lon="-1.4047466197307201">
+ </trkpt>
+ <trkpt lat="50.90030020548411" lon="-1.404713139163847">
+ </trkpt>
+ <trkpt lat="50.90023516394009" lon="-1.404633143321385">
+ </trkpt>
+ <trkpt lat="50.90024609037792" lon="-1.4039437333307951">
+ </trkpt>
+ <trkpt lat="50.90018031013936" lon="-1.4038679559430145">
+ </trkpt>
+ <trkpt lat="50.8994913035919" lon="-1.403812474422933">
+ </trkpt>
+ <trkpt lat="50.89887472267534" lon="-1.403830299089678">
+ </trkpt>
+ <trkpt lat="50.898373807934426" lon="-1.4039238831798881">
+ </trkpt>
+ <trkpt lat="50.89751893094865" lon="-1.4040832908380838">
+ </trkpt>
+ <trkpt lat="50.896849035979706" lon="-1.4042379529545828">
+ </trkpt>
+ <trkpt lat="50.896532945912476" lon="-1.4045205446291842">
+ </trkpt>
+ <trkpt lat="50.89643044366278" lon="-1.404504712579317">
+ </trkpt>
+ <trkpt lat="50.8963465597906" lon="-1.4043776716135077">
+ </trkpt>
+ <trkpt lat="50.89613177850224" lon="-1.4032536392542871">
+ </trkpt>
+ <trkpt lat="50.89610751759247" lon="-1.4027960177172492">
+ </trkpt>
+ <trkpt lat="50.89618082780473" lon="-1.402511517446233">
+ </trkpt>
+ <trkpt lat="50.89638230279852" lon="-1.4020139802048763">
+ </trkpt>
+ <trkpt lat="50.89657300523864" lon="-1.4016744041443394">
+ </trkpt>
+ <trkpt lat="50.89703289956441" lon="-1.4015397766549245">
+ </trkpt>
+ <trkpt lat="50.897829746346225" lon="-1.400513924581253">
+ </trkpt>
+ <trkpt lat="50.89767227614247" lon="-1.3990570874048585">
+ </trkpt>
+ <trkpt lat="50.897486334438966" lon="-1.3978262175885954">
+ </trkpt>
+ <trkpt lat="50.897392576497325" lon="-1.397403496539838">
+ </trkpt>
+ <trkpt lat="50.89730446596853" lon="-1.3973514506859277">
+ </trkpt>
+ <trkpt lat="50.89713544924383" lon="-1.3974328363046487">
+ </trkpt>
+ <trkpt lat="50.89700090481612" lon="-1.3977778463245527">
+ </trkpt>
+ <trkpt lat="50.896940860459615" lon="-1.3985358495978997">
+ </trkpt>
+ <trkpt lat="50.896865021208384" lon="-1.3986933208872843">
+ </trkpt>
+ <trkpt lat="50.896758602337925" lon="-1.3987409612494623">
+ </trkpt>
+ <trkpt lat="50.896205002299624" lon="-1.398531651045157">
+ </trkpt>
+ <trkpt lat="50.895923319746686" lon="-1.3984299826997648">
+ </trkpt>
+ <trkpt lat="50.895773059252704" lon="-1.3981108278459158">
+ </trkpt>
+ <trkpt lat="50.89550488942174" lon="-1.398169109324386">
+ </trkpt>
+ <trkpt lat="50.89492261034825" lon="-1.3980019206408216">
+ </trkpt>
+ <trkpt lat="50.8940391921321" lon="-1.3976330584342718">
+ </trkpt>
+ <trkpt lat="50.89400677189769" lon="-1.3975671816229178">
+ </trkpt>
+ <trkpt lat="50.89405714800631" lon="-1.3972132870360223">
+ </trkpt>
+ <trkpt lat="50.894033573665396" lon="-1.3970043888316508">
+ </trkpt>
+ <trkpt lat="50.8938869214068" lon="-1.396529941868323">
+ </trkpt>
+ <trkpt lat="50.893689541423875" lon="-1.3950163745945263">
+ </trkpt>
+ <trkpt lat="50.89366536561377" lon="-1.3949788859521974">
+ </trkpt>
+ <trkpt lat="50.89354098276008" lon="-1.3950102491573826">
+ </trkpt>
+ <trkpt lat="50.89345730201993" lon="-1.3949748574886274">
+ </trkpt>
+ <trkpt lat="50.893296380636684" lon="-1.3947404433185928">
+ </trkpt>
+ <trkpt lat="50.89321333961815" lon="-1.394782496350573">
+ </trkpt>
+ <trkpt lat="50.89319137592511" lon="-1.3949629308377884">
+ </trkpt>
+ <trkpt lat="50.89336791190969" lon="-1.3953336635746296">
+ </trkpt>
+ <trkpt lat="50.893429955875675" lon="-1.3953888863076813">
+ </trkpt>
+ <trkpt lat="50.89350302058808" lon="-1.395365769098011">
+ </trkpt>
+ <trkpt lat="50.89352692506417" lon="-1.3952590941580216">
+ </trkpt>
+ <trkpt lat="50.893508411526746" lon="-1.3951011759862977">
+ </trkpt>
+ <trkpt lat="50.89354347563417" lon="-1.3950137575502435">
+ </trkpt>
+ <trkpt lat="50.893663134423" lon="-1.3949808203355554">
+ </trkpt>
+ <trkpt lat="50.89368987829803" lon="-1.3950150879240986">
+ </trkpt>
+ <trkpt lat="50.89388481344618" lon="-1.396524966724835">
+ </trkpt>
+ <trkpt lat="50.89403278701577" lon="-1.397009767848505">
+ </trkpt>
+ <trkpt lat="50.89405293056597" lon="-1.3972154214272585">
+ </trkpt>
+ <trkpt lat="50.89400665109331" lon="-1.3975658323157298">
+ </trkpt>
+ <trkpt lat="50.894035401710305" lon="-1.397626319551046">
+ </trkpt>
+ <trkpt lat="50.89492543762919" lon="-1.3980016520159237">
+ </trkpt>
+ <trkpt lat="50.89550279449911" lon="-1.398170213685916">
+ </trkpt>
+ <trkpt lat="50.89565787376361" lon="-1.3984621755169806">
+ </trkpt>
+ <trkpt lat="50.89592455277748" lon="-1.3984304152755282">
+ </trkpt>
+ <trkpt lat="50.89619749028084" lon="-1.3985276810149754">
+ </trkpt>
+ <trkpt lat="50.8967583843489" lon="-1.3987400776296872">
+ </trkpt>
+ <trkpt lat="50.89689126609175" lon="-1.3989126093298614">
+ </trkpt>
+ <trkpt lat="50.89686973112739" lon="-1.3996333928539189">
+ </trkpt>
+ <trkpt lat="50.89678860324341" lon="-1.4004291608592045">
+ </trkpt>
+ <trkpt lat="50.89660831715814" lon="-1.4012298408106363">
+ </trkpt>
+ <trkpt lat="50.89638230235851" lon="-1.4020124391148507">
+ </trkpt>
+ <trkpt lat="50.896181385866996" lon="-1.4025081905290882">
+ </trkpt>
+ <trkpt lat="50.8961062651468" lon="-1.4027992688775768">
+ </trkpt>
+ <trkpt lat="50.896130053688616" lon="-1.4032565412183065">
+ </trkpt>
+ <trkpt lat="50.8963466496169" lon="-1.404377355874733">
+ </trkpt>
+ <trkpt lat="50.8964280294949" lon="-1.4045043968405428">
+ </trkpt>
+ <trkpt lat="50.896538205103155" lon="-1.4045242469914505">
+ </trkpt>
+ <trkpt lat="50.89684329941986" lon="-1.404238428360424">
+ </trkpt>
+ <trkpt lat="50.8975222988971" lon="-1.4040804016273893">
+ </trkpt>
+ <trkpt lat="50.89837280980361" lon="-1.4039257692925182">
+ </trkpt>
+ <trkpt lat="50.898873774513575" lon="-1.4038318266632464">
+ </trkpt>
+ <trkpt lat="50.899491761278156" lon="-1.40381083858318">
+ </trkpt>
+ <trkpt lat="50.900179673817654" lon="-1.4038689925074306">
+ </trkpt>
+ <trkpt lat="50.90024635331904" lon="-1.4039441409395221">
+ </trkpt>
+ <trkpt lat="50.900232189748905" lon="-1.4046311727797367">
+ </trkpt>
+ <trkpt lat="50.900302443211395" lon="-1.4047190535225447">
+ </trkpt>
+ <trkpt lat="50.900413399581005" lon="-1.4047524582043411">
+ </trkpt>
+ <trkpt lat="50.90115728945764" lon="-1.4047827906242598">
+ </trkpt>
+ <trkpt lat="50.901640131269886" lon="-1.4049620646985328">
+ </trkpt>
+ <trkpt lat="50.90238641465812" lon="-1.4054774892433946">
+ </trkpt>
+ <trkpt lat="50.90273894490854" lon="-1.405592160906379">
+ </trkpt>
+ <trkpt lat="50.90319341892739" lon="-1.405796816964795">
+ </trkpt>
+ <trkpt lat="50.904607859579315" lon="-1.406179749577147">
+ </trkpt>
+ <trkpt lat="50.905251507472464" lon="-1.406326415820224">
+ </trkpt>
+ <trkpt lat="50.90609556711578" lon="-1.4065444038672295">
+ </trkpt>
+ <trkpt lat="50.906582881829635" lon="-1.406830152211754">
+ </trkpt>
+ <trkpt lat="50.90679692543821" lon="-1.4072044163721162">
+ </trkpt>
+ <trkpt lat="50.90688464924575" lon="-1.4074536243267861">
+ </trkpt>
+ <trkpt lat="50.906901046250134" lon="-1.4076319669368693">
+ </trkpt>
+ <trkpt lat="50.90688414808858" lon="-1.4079525468740277">
+ </trkpt>
+ <trkpt lat="50.906918512373856" lon="-1.4083651354133502">
+ </trkpt>
+ <trkpt lat="50.90696486005155" lon="-1.4090192827783095">
+ </trkpt>
+ <trkpt lat="50.90712652963618" lon="-1.4110462085634305">
+ </trkpt>
+ <trkpt lat="50.90711821837297" lon="-1.4113290575434165">
+ </trkpt>
+ <trkpt lat="50.90709176705272" lon="-1.4115882637666801">
+ </trkpt>
+ <trkpt lat="50.90697487376026" lon="-1.4123283029346132">
+ </trkpt>
+ <trkpt lat="50.906976751330454" lon="-1.4126717105453146">
+ </trkpt>
+ <trkpt lat="50.90707299139423" lon="-1.412737587504232">
+ </trkpt>
+ <trkpt lat="50.90702354879057" lon="-1.413292399222101">
+ </trkpt>
+ <trkpt lat="50.90704309209376" lon="-1.4139183000223146">
+ </trkpt>
+ <trkpt lat="50.90706627239544" lon="-1.4139780601820413">
+ </trkpt>
+ <trkpt lat="50.90710319785529" lon="-1.413990962780131">
+ </trkpt>
+ <trkpt lat="50.90713119591095" lon="-1.4139544017548709">
+ </trkpt>
+ <trkpt lat="50.90714951110255" lon="-1.4138758319048672">
+ </trkpt>
+ <trkpt lat="50.90710991684878" lon="-1.4132804891315567">
+ </trkpt>
+ <trkpt lat="50.907165133817124" lon="-1.4127114108471304">
+ </trkpt>
+ <trkpt lat="50.907192045538686" lon="-1.4122895951403431">
+ </trkpt>
+ <trkpt lat="50.90712994420169" lon="-1.4120597048507366">
+ </trkpt>
+ <trkpt lat="50.90719905819093" lon="-1.4116282169931595">
+ </trkpt>
+ <trkpt lat="50.90722140854919" lon="-1.4111986298439005">
+ </trkpt>
+ <trkpt lat="50.907113174338214" lon="-1.4098100196467485">
+ </trkpt>
+ <trkpt lat="50.90696982242787" lon="-1.4084054727884836">
+ </trkpt>
+ <trkpt lat="50.90695391435455" lon="-1.4081230524386659">
+ </trkpt>
+ <trkpt lat="50.90699692296758" lon="-1.4078397313856648">
+ </trkpt>
+ <trkpt lat="50.90707927298402" lon="-1.40764501247332">
+ </trkpt>
+ <trkpt lat="50.907119953562386" lon="-1.4074504809944248">
+ </trkpt>
+ <trkpt lat="50.90710993988486" lon="-1.4072896947720732">
+ </trkpt>
+ <trkpt lat="50.90707614370728" lon="-1.407127916042176">
+ </trkpt>
+ <trkpt lat="50.906989775586446" lon="-1.4068698640803763">
+ </trkpt>
+ <trkpt lat="50.90697170301636" lon="-1.406549360852549">
+ </trkpt>
+ <trkpt lat="50.90692671816205" lon="-1.404541842052056">
+ </trkpt>
+ <trkpt lat="50.90884225101527" lon="-1.4046992688941846">
+ </trkpt>
+ <trkpt lat="50.9103254762355" lon="-1.4048245827823584">
+ </trkpt>
+ <trkpt lat="50.9107588927861" lon="-1.4048630902125017">
+ </trkpt>
+ <trkpt lat="50.91129641811278" lon="-1.404408460142413">
+ </trkpt>
+ <trkpt lat="50.912514179939514" lon="-1.4032818539445386">
+ </trkpt>
+ <trkpt lat="50.91346553069003" lon="-1.4024577052112865">
+ </trkpt>
+ <trkpt lat="50.9138685855199" lon="-1.4023605120835456">
+ </trkpt>
+ <trkpt lat="50.91405943251336" lon="-1.402327637118034">
+ </trkpt>
+ <trkpt lat="50.91425429982065" lon="-1.402331490618383">
+ </trkpt>
+ <trkpt lat="50.91538141467132" lon="-1.402638505139009">
+ </trkpt>
+ <trkpt lat="50.91593308844944" lon="-1.4028390559694166">
+ </trkpt>
+ <trkpt lat="50.916231101034626" lon="-1.4029382724944675">
+ </trkpt>
+ <trkpt lat="50.91654048073624" lon="-1.4030619277639798">
+ </trkpt>
+ <trkpt lat="50.91852160800149" lon="-1.4038834276918808">
+ </trkpt>
+ <trkpt lat="50.91897640643002" lon="-1.403987109733912">
+ </trkpt>
+ <trkpt lat="50.92032234200917" lon="-1.4046059731849194">
+ </trkpt>
+ <trkpt lat="50.92175235370102" lon="-1.4049565810286118">
+ </trkpt>
+ <trkpt lat="50.92323540415272" lon="-1.4052074327574204">
+ </trkpt>
+ <trkpt lat="50.92330476561471" lon="-1.4043126522087974">
+ </trkpt>
+ <trkpt lat="50.923445618076244" lon="-1.4037841769373434">
+ </trkpt>
+ <trkpt lat="50.924489080053995" lon="-1.4013977586639144">
+ </trkpt>
+ <trkpt lat="50.926021934332844" lon="-1.3978816227109718">
+ </trkpt>
+ <trkpt lat="50.92536864463438" lon="-1.396133961748898">
+ </trkpt>
+ <trkpt lat="50.92465339917508" lon="-1.393968695660324">
+ </trkpt>
+ <trkpt lat="50.925179308754274" lon="-1.3934390158965395">
+ </trkpt>
+ <trkpt lat="50.92587368740231" lon="-1.392655024311904">
+ </trkpt>
+ <trkpt lat="50.926212009245674" lon="-1.3922242793238673">
+ </trkpt>
+ <trkpt lat="50.92658173623098" lon="-1.3916238122589113">
+ </trkpt>
+ <trkpt lat="50.92688389671198" lon="-1.3911404610843097">
+ </trkpt>
+ <trkpt lat="50.92695771615849" lon="-1.3910223526864096">
+ </trkpt>
+ <trkpt lat="50.92703426761708" lon="-1.391025423417552">
+ </trkpt>
+ <trkpt lat="50.927291315187375" lon="-1.391478731255188">
+ </trkpt>
+ <trkpt lat="50.9291116021986" lon="-1.3907872870934017">
+ </trkpt>
+ <trkpt lat="50.92974286274807" lon="-1.390647956220023">
+ </trkpt>
+ <trkpt lat="50.93027930529069" lon="-1.3906347422638812">
+ </trkpt>
+ <trkpt lat="50.93102083420498" lon="-1.3907658205383429">
+ </trkpt>
+ <trkpt lat="50.9315214536277" lon="-1.393019024949069">
+ </trkpt>
+ <trkpt lat="50.93225614910195" lon="-1.3952128079116057">
+ </trkpt>
+ <trkpt lat="50.93281948828285" lon="-1.3954457538373262">
+ </trkpt>
+ <trkpt lat="50.93342877780136" lon="-1.3956716264625637">
+ </trkpt>
+ <trkpt lat="50.93419888149234" lon="-1.3962293564096209">
+ </trkpt>
+ <trkpt lat="50.934456947476555" lon="-1.3963709101843775">
+ </trkpt>
+ <trkpt lat="50.93477581509559" lon="-1.3964211076866837">
+ </trkpt>
+ <trkpt lat="50.93519993609559" lon="-1.3962920425704037">
+ </trkpt>
+ <trkpt lat="50.93562536416281" lon="-1.3961105648216663">
+ </trkpt>
+ <trkpt lat="50.93569676455895" lon="-1.3961093670834637">
+ </trkpt>
+ <trkpt lat="50.93569845029133" lon="-1.396193054766114">
+ </trkpt>
+ <trkpt lat="50.93571891176462" lon="-1.396362469323285">
+ </trkpt>
+ <trkpt lat="50.93576438819076" lon="-1.3964413369014559">
+ </trkpt>
+ <trkpt lat="50.93609042062749" lon="-1.396540512143667">
+ </trkpt>
+ <trkpt lat="50.936459320528535" lon="-1.3971062698011694">
+ </trkpt>
+ <trkpt lat="50.937080164287764" lon="-1.3972331012373267">
+ </trkpt>
+ <trkpt lat="50.93714430028705" lon="-1.3963630020371174">
+ </trkpt>
+ <trkpt lat="50.937175300206924" lon="-1.3963434071630627">
+ </trkpt>
+ <trkpt lat="50.93785155077349" lon="-1.3964590190757231">
+ </trkpt>
+ <trkpt lat="50.93791191107203" lon="-1.3964200186254823">
+ </trkpt>
+ <trkpt lat="50.9379640113226" lon="-1.3963233738402345">
+ </trkpt>
+ <trkpt lat="50.938004912943384" lon="-1.3961466353922247">
+ </trkpt>
+ <trkpt lat="50.93830479343969" lon="-1.3933163026922226">
+ </trkpt>
+ <trkpt lat="50.93856634814012" lon="-1.3901081284841543">
+ </trkpt>
+ <trkpt lat="50.93860863471744" lon="-1.3891961062070992">
+ </trkpt>
+ <trkpt lat="50.938516799164844" lon="-1.3868346794358606">
+ </trkpt>
+ <trkpt lat="50.93841610926034" lon="-1.3844247807736554">
+ </trkpt>
+ <trkpt lat="50.936846246223716" lon="-1.3812011446228891">
+ </trkpt>
+ <trkpt lat="50.93665234259918" lon="-1.3805375456044044">
+ </trkpt>
+ <trkpt lat="50.936659596643764" lon="-1.3801408247276097">
+ </trkpt>
+ <trkpt lat="50.936656024920616" lon="-1.3788695540602445">
+ </trkpt>
+ <trkpt lat="50.93669838447263" lon="-1.3781820088283685">
+ </trkpt>
+ <trkpt lat="50.93694793168109" lon="-1.3779900608767666">
+ </trkpt>
+ <trkpt lat="50.93714620007283" lon="-1.3776476457736095">
+ </trkpt>
+ <trkpt lat="50.937348220309126" lon="-1.3769310553258443">
+ </trkpt>
+ <trkpt lat="50.93754632451428" lon="-1.375960744025551">
+ </trkpt>
+ <trkpt lat="50.937630648735706" lon="-1.3758313594532836">
+ </trkpt>
+ <trkpt lat="50.93853682040445" lon="-1.3758251197789304">
+ </trkpt>
+ <trkpt lat="50.93920600919963" lon="-1.3757811673055762">
+ </trkpt>
+ <trkpt lat="50.93964402182343" lon="-1.3757721675919288">
+ </trkpt>
+ <trkpt lat="50.94010824169678" lon="-1.3756368254866667">
+ </trkpt>
+ <trkpt lat="50.940355231676186" lon="-1.3755104752890508">
+ </trkpt>
+ <trkpt lat="50.94045378351913" lon="-1.3755057232773396">
+ </trkpt>
+ <trkpt lat="50.940916265901905" lon="-1.3758075367844729">
+ </trkpt>
+ <trkpt lat="50.940991358069134" lon="-1.3758047533462274">
+ </trkpt>
+ <trkpt lat="50.941507890819004" lon="-1.3752338674232425">
+ </trkpt>
+ <trkpt lat="50.94208863731823" lon="-1.3746942267731468">
+ </trkpt>
+ <trkpt lat="50.94205573128066" lon="-1.3739872779462416">
+ </trkpt>
+ <trkpt lat="50.94200501349514" lon="-1.3735227390405518">
+ </trkpt>
+ <trkpt lat="50.942083248211205" lon="-1.3731416615175762">
+ </trkpt>
+ <trkpt lat="50.9421508912301" lon="-1.3728474474960601">
+ </trkpt>
+ <trkpt lat="50.94224834945251" lon="-1.3726493777750672">
+ </trkpt>
+ <trkpt lat="50.943110032113644" lon="-1.3715424818737278">
+ </trkpt>
+ <trkpt lat="50.944142183741356" lon="-1.3702395888904793">
+ </trkpt>
+ <trkpt lat="50.944668374399875" lon="-1.369576614908956">
+ </trkpt>
+ <trkpt lat="50.94596558784118" lon="-1.3680377327348594">
+ </trkpt>
+ <trkpt lat="50.94664830375188" lon="-1.3673387311544039">
+ </trkpt>
+ <trkpt lat="50.94700059108037" lon="-1.3669194263744633">
+ </trkpt>
+ <trkpt lat="50.94765544792511" lon="-1.3659401995240779">
+ </trkpt>
+ <trkpt lat="50.94787044001649" lon="-1.3654181548452817">
+ </trkpt>
+ <trkpt lat="50.948059177930084" lon="-1.3651121761154554">
+ </trkpt>
+ <trkpt lat="50.94804022862618" lon="-1.3647837196758723">
+ </trkpt>
+ <trkpt lat="50.94793882936343" lon="-1.364517890495079">
+ </trkpt>
+ <trkpt lat="50.94795700170869" lon="-1.3643255985280005">
+ </trkpt>
+ <trkpt lat="50.94809228449993" lon="-1.3641333065609227">
+ </trkpt>
+ <trkpt lat="50.94900492826686" lon="-1.363783976154064">
+ </trkpt>
+ <trkpt lat="50.94970959006663" lon="-1.3635692501241612">
+ </trkpt>
+ <trkpt lat="50.94900492826686" lon="-1.3637807712879466">
+ </trkpt>
+ <trkpt lat="50.948090265356676" lon="-1.3641333065609227">
+ </trkpt>
+ <trkpt lat="50.94795700170868" lon="-1.3643288033941185">
+ </trkpt>
+ <trkpt lat="50.94793882936341" lon="-1.3645243002273146">
+ </trkpt>
+ <trkpt lat="50.9478072601364" lon="-1.3647390617373651">
+ </trkpt>
+ <trkpt lat="50.947719833750206" lon="-1.365151545868109">
+ </trkpt>
+ <trkpt lat="50.94773715200268" lon="-1.3655162727698977">
+ </trkpt>
+ <trkpt lat="50.94765251754173" lon="-1.3659455861339014">
+ </trkpt>
+ <trkpt lat="50.94718066741214" lon="-1.3666421094198942">
+ </trkpt>
+ <trkpt lat="50.947000269954586" lon="-1.366920453100236">
+ </trkpt>
+ <trkpt lat="50.94664476638959" lon="-1.3673443456249295">
+ </trkpt>
+ <trkpt lat="50.945963819134086" lon="-1.3680433472053855">
+ </trkpt>
+ <trkpt lat="50.94466203246378" lon="-1.3695817121294398">
+ </trkpt>
+ <trkpt lat="50.944142120470076" lon="-1.3702391291280986">
+ </trkpt>
+ <trkpt lat="50.943108338792385" lon="-1.3715445380136377">
+ </trkpt>
+ <trkpt lat="50.94224845662901" lon="-1.3726547307561423">
+ </trkpt>
+ <trkpt lat="50.94214703739668" lon="-1.3728419242388714">
+ </trkpt>
+ <trkpt lat="50.941913143288794" lon="-1.3732567923928407">
+ </trkpt>
+ <trkpt lat="50.9418346606051" lon="-1.3733301467378625">
+ </trkpt>
+ <trkpt lat="50.9417855641885" lon="-1.373431473720828">
+ </trkpt>
+ <trkpt lat="50.94178462954267" lon="-1.3735246782167565">
+ </trkpt>
+ <trkpt lat="50.941811830502516" lon="-1.3736101250789967">
+ </trkpt>
+ <trkpt lat="50.941903137097476" lon="-1.3736895256826283">
+ </trkpt>
+ <trkpt lat="50.94197318039127" lon="-1.3737927464673467">
+ </trkpt>
+ <trkpt lat="50.94205573128064" lon="-1.3739872779462423">
+ </trkpt>
+ <trkpt lat="50.94208671640247" lon="-1.3746946600107683">
+ </trkpt>
+ <trkpt lat="50.9415069561676" lon="-1.375237746240086">
+ </trkpt>
+ <trkpt lat="50.9409903792152" lon="-1.375803475540954">
+ </trkpt>
+ <trkpt lat="50.940913764300646" lon="-1.3758055517693821">
+ </trkpt>
+ <trkpt lat="50.940455969004724" lon="-1.375503829475586">
+ </trkpt>
+ <trkpt lat="50.940357154674494" lon="-1.3755117695359484">
+ </trkpt>
+ <trkpt lat="50.94010824169678" lon="-1.3756348404715761">
+ </trkpt>
+ <trkpt lat="50.9396432461699" lon="-1.375772302766611">
+ </trkpt>
+ <trkpt lat="50.93920614653104" lon="-1.3757818630865624">
+ </trkpt>
+ <trkpt lat="50.93853086449635" lon="-1.3758202096105172">
+ </trkpt>
+ <trkpt lat="50.93762967118759" lon="-1.3758333419806512">
+ </trkpt>
+ <trkpt lat="50.93754636959413" lon="-1.3759613432035367">
+ </trkpt>
+ <trkpt lat="50.937348494521316" lon="-1.376933370449014">
+ </trkpt>
+ <trkpt lat="50.937145783580505" lon="-1.3776465431817642">
+ </trkpt>
+ <trkpt lat="50.93694756414976" lon="-1.3779910080020117">
+ </trkpt>
+ <trkpt lat="50.93669832293507" lon="-1.3781809652919177">
+ </trkpt>
+ <trkpt lat="50.93665369791798" lon="-1.3788773905142764">
+ </trkpt>
+ <trkpt lat="50.93665691535516" lon="-1.3801473005072467">
+ </trkpt>
+ <trkpt lat="50.93665296723523" lon="-1.380541916793008">
+ </trkpt>
+ <trkpt lat="50.93684245936851" lon="-1.3812023495201582">
+ </trkpt>
+ <trkpt lat="50.93841429545403" lon="-1.3844161650152416">
+ </trkpt>
+ <trkpt lat="50.93851856815526" lon="-1.3868318722005983">
+ </trkpt>
+ <trkpt lat="50.93860872864074" lon="-1.3891985276660623">
+ </trkpt>
+ <trkpt lat="50.93856691501372" lon="-1.39010577756465">
+ </trkpt>
+ </trkseg>
+ </trk>
+</gpx> \ No newline at end of file
diff --git a/res/raw/u1e.gpx b/res/raw/u1e.gpx
new file mode 100644
index 0000000..da75fed
--- /dev/null
+++ b/res/raw/u1e.gpx
@@ -0,0 +1,244 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
+ <metadata>
+ <author>
+ <name>chrisb8</name>
+ </author>
+ <copyright author="chrisb8">
+ <year>2011</year>
+ <license>http://creativecommons.org/licenses/by-sa/2.5</license>
+ </copyright>
+ <bounds minlat="50.9478082" minlon="-1.3654174" maxlat="50.9712154" maxlon="-1.3504035" />
+ </metadata>
+ <trk> <trkseg>
+ <trkpt lat="50.94787108843824" lon="-1.3654173877340656">
+ </trkpt>
+ <trkpt lat="50.94824373142839" lon="-1.3651590429216773">
+ </trkpt>
+ <trkpt lat="50.948485019740474" lon="-1.3650049425072706">
+ </trkpt>
+ <trkpt lat="50.94919745543585" lon="-1.3643658790239943">
+ </trkpt>
+ <trkpt lat="50.94929454001586" lon="-1.3643545481111707">
+ </trkpt>
+ <trkpt lat="50.95007406473399" lon="-1.364610626740994">
+ </trkpt>
+ <trkpt lat="50.950576996975585" lon="-1.3649140283639334">
+ </trkpt>
+ <trkpt lat="50.95068198669088" lon="-1.3649300526945232">
+ </trkpt>
+ <trkpt lat="50.95076274784898" lon="-1.364853135907692">
+ </trkpt>
+ <trkpt lat="50.950799090324324" lon="-1.3646095660827264">
+ </trkpt>
+ <trkpt lat="50.950872784701005" lon="-1.3641160167005597">
+ </trkpt>
+ <trkpt lat="50.951049448826836" lon="-1.363475043476967">
+ </trkpt>
+ <trkpt lat="50.95132201501802" lon="-1.3629013724418513">
+ </trkpt>
+ <trkpt lat="50.951634959414505" lon="-1.362475125248162">
+ </trkpt>
+ <trkpt lat="50.952389124755705" lon="-1.3617988041548212">
+ </trkpt>
+ <trkpt lat="50.95370854161666" lon="-1.3606936846941116">
+ </trkpt>
+ <trkpt lat="50.95490737444371" lon="-1.359609671797216">
+ </trkpt>
+ <trkpt lat="50.95610326191012" lon="-1.358377598941652">
+ </trkpt>
+ <trkpt lat="50.957474021400614" lon="-1.3572483095646855">
+ </trkpt>
+ <trkpt lat="50.958595992724845" lon="-1.3561832037592256">
+ </trkpt>
+ <trkpt lat="50.95998914078622" lon="-1.3548506884111189">
+ </trkpt>
+ <trkpt lat="50.9606276752609" lon="-1.354334136134244">
+ </trkpt>
+ <trkpt lat="50.96190657650706" lon="-1.3533642099965062">
+ </trkpt>
+ <trkpt lat="50.96374700306114" lon="-1.3520185368920492">
+ </trkpt>
+ <trkpt lat="50.965465513134546" lon="-1.3510930816836144">
+ </trkpt>
+ <trkpt lat="50.965844968612814" lon="-1.3510674427546705">
+ </trkpt>
+ <trkpt lat="50.96606295227306" lon="-1.3512725541862203">
+ </trkpt>
+ <trkpt lat="50.96612753982781" lon="-1.3512597347217488">
+ </trkpt>
+ <trkpt lat="50.96620827414496" lon="-1.3511251303447942">
+ </trkpt>
+ <trkpt lat="50.966329375357596" lon="-1.3509841162356038">
+ </trkpt>
+ <trkpt lat="50.966716897116484" lon="-1.3508687410553568">
+ </trkpt>
+ <trkpt lat="50.96691469343477" lon="-1.3508559215908849">
+ </trkpt>
+ <trkpt lat="50.96706707675866" lon="-1.3509408505430112">
+ </trkpt>
+ <trkpt lat="50.96712542640542" lon="-1.3509627287068873">
+ </trkpt>
+ <trkpt lat="50.96720111320597" lon="-1.3509034386837049">
+ </trkpt>
+ <trkpt lat="50.96726588074095" lon="-1.3507806072371131">
+ </trkpt>
+ <trkpt lat="50.96736762373301" lon="-1.3507095442835682">
+ </trkpt>
+ <trkpt lat="50.967704861140035" lon="-1.3506556174585123">
+ </trkpt>
+ <trkpt lat="50.96828612535391" lon="-1.3505514593096783">
+ </trkpt>
+ <trkpt lat="50.96916608094783" lon="-1.3505290252468527">
+ </trkpt>
+ <trkpt lat="50.96926099696185" lon="-1.3505894069129216">
+ </trkpt>
+ <trkpt lat="50.96928194733831" lon="-1.3507127491496862">
+ </trkpt>
+ <trkpt lat="50.96928668474658" lon="-1.3508522840904396">
+ </trkpt>
+ <trkpt lat="50.96925956986227" lon="-1.351486815208586">
+ </trkpt>
+ <trkpt lat="50.969268968434434" lon="-1.3516012712442405">
+ </trkpt>
+ <trkpt lat="50.96928396556087" lon="-1.351675811418135">
+ </trkpt>
+ <trkpt lat="50.96932378929944" lon="-1.3517746203943164">
+ </trkpt>
+ <trkpt lat="50.969527863810384" lon="-1.3517859513071402">
+ </trkpt>
+ <trkpt lat="50.9701985919006" lon="-1.3518131454979176">
+ </trkpt>
+ <trkpt lat="50.97076656258198" lon="-1.3517972822199642">
+ </trkpt>
+ <trkpt lat="50.970832206986834" lon="-1.3517904836722696">
+ </trkpt>
+ <trkpt lat="50.97089851552719" lon="-1.3517575355041438">
+ </trkpt>
+ <trkpt lat="50.97094494390044" lon="-1.3516975701871126">
+ </trkpt>
+ <trkpt lat="50.97104626418424" lon="-1.351219405665938">
+ </trkpt>
+ <trkpt lat="50.97110133939857" lon="-1.3509258727465316">
+ </trkpt>
+ <trkpt lat="50.971188968434426" lon="-1.3507231116842449">
+ </trkpt>
+ <trkpt lat="50.971215364370195" lon="-1.350619808032266">
+ </trkpt>
+ <trkpt lat="50.971204982428866" lon="-1.3505025143445415">
+ </trkpt>
+ <trkpt lat="50.97116793808856" lon="-1.3504275160651884">
+ </trkpt>
+ <trkpt lat="50.97111803433519" lon="-1.350403466061196">
+ </trkpt>
+ <trkpt lat="50.9710609765097" lon="-1.3504211063329523">
+ </trkpt>
+ <trkpt lat="50.971004879869675" lon="-1.3504715654195512">
+ </trkpt>
+ <trkpt lat="50.97094997838439" lon="-1.3505124450173143">
+ </trkpt>
+ <trkpt lat="50.97089357015096" lon="-1.350532752348801">
+ </trkpt>
+ <trkpt lat="50.970104405136325" lon="-1.35048969488007">
+ </trkpt>
+ <trkpt lat="50.96967057272583" lon="-1.3504489035939033">
+ </trkpt>
+ <trkpt lat="50.969525142527715" lon="-1.3504179014668347">
+ </trkpt>
+ <trkpt lat="50.9693745019475" lon="-1.350420268022703">
+ </trkpt>
+ <trkpt lat="50.969163810660255" lon="-1.3505289309044026">
+ </trkpt>
+ <trkpt lat="50.9682861517122" lon="-1.3505518676640975">
+ </trkpt>
+ <trkpt lat="50.96770165214216" lon="-1.3506534591265038">
+ </trkpt>
+ <trkpt lat="50.967370651191644" lon="-1.3507095442835682">
+ </trkpt>
+ <trkpt lat="50.967232668242936" lon="-1.3507070401824306">
+ </trkpt>
+ <trkpt lat="50.9671415729332" lon="-1.3507928708026353">
+ </trkpt>
+ <trkpt lat="50.96704497507264" lon="-1.3508095682659413">
+ </trkpt>
+ <trkpt lat="50.966909077366786" lon="-1.3507956295263186">
+ </trkpt>
+ <trkpt lat="50.9667154590204" lon="-1.350869844143902">
+ </trkpt>
+ <trkpt lat="50.96632925369248" lon="-1.3509838170216486">
+ </trkpt>
+ <trkpt lat="50.966168369293506" lon="-1.351067571434096">
+ </trkpt>
+ <trkpt lat="50.96610616547903" lon="-1.3510941282177242">
+ </trkpt>
+ <trkpt lat="50.96604258707625" lon="-1.3510700917218392">
+ </trkpt>
+ <trkpt lat="50.965943687165655" lon="-1.3510364406276005">
+ </trkpt>
+ <trkpt lat="50.96584363068131" lon="-1.351066613211582">
+ </trkpt>
+ <trkpt lat="50.96546544964621" lon="-1.3510931436528537">
+ </trkpt>
+ <trkpt lat="50.96374697788408" lon="-1.3520201262032712">
+ </trkpt>
+ <trkpt lat="50.961909383478634" lon="-1.3533662386467666">
+ </trkpt>
+ <trkpt lat="50.96060625912123" lon="-1.354283284493558">
+ </trkpt>
+ <trkpt lat="50.95998889845663" lon="-1.354853243224739">
+ </trkpt>
+ <trkpt lat="50.95859400632111" lon="-1.3561874748873164">
+ </trkpt>
+ <trkpt lat="50.95747715352152" lon="-1.3572451183955767">
+ </trkpt>
+ <trkpt lat="50.95610270290364" lon="-1.3583760102056017">
+ </trkpt>
+ <trkpt lat="50.954905941689695" lon="-1.359609457493159">
+ </trkpt>
+ <trkpt lat="50.95371125586368" lon="-1.3606924847735193">
+ </trkpt>
+ <trkpt lat="50.95239142094021" lon="-1.361799206667288">
+ </trkpt>
+ <trkpt lat="50.951633003304735" lon="-1.3624765203201192">
+ </trkpt>
+ <trkpt lat="50.95132466152284" lon="-1.362899357776185">
+ </trkpt>
+ <trkpt lat="50.95104776823189" lon="-1.3634721520969866">
+ </trkpt>
+ <trkpt lat="50.950874429805644" lon="-1.3641150370246617">
+ </trkpt>
+ <trkpt lat="50.95067358887209" lon="-1.3645717533377886">
+ </trkpt>
+ <trkpt lat="50.95058650088624" lon="-1.3646556020926868">
+ </trkpt>
+ <trkpt lat="50.95045943779448" lon="-1.3646669330055108">
+ </trkpt>
+ <trkpt lat="50.95026527329793" lon="-1.3646216093542145">
+ </trkpt>
+ <trkpt lat="50.95007243421656" lon="-1.3646048545639327">
+ </trkpt>
+ <trkpt lat="50.949290155509516" lon="-1.3643553467189815">
+ </trkpt>
+ <trkpt lat="50.949197455532875" lon="-1.3643650751987468">
+ </trkpt>
+ <trkpt lat="50.948484010274434" lon="-1.3650078462450104">
+ </trkpt>
+ <trkpt lat="50.94840580854819" lon="-1.3650545250275814">
+ </trkpt>
+ <trkpt lat="50.948276468186705" lon="-1.3650703135020463">
+ </trkpt>
+ <trkpt lat="50.94815939301556" lon="-1.3650113927553613">
+ </trkpt>
+ <trkpt lat="50.94804231754952" lon="-1.3648119686896583">
+ </trkpt>
+ <trkpt lat="50.94795808014156" lon="-1.3647417170301492">
+ </trkpt>
+ <trkpt lat="50.94786384828395" lon="-1.3647190552045008">
+ </trkpt>
+ <trkpt lat="50.947808165732845" lon="-1.3647371846650196">
+ </trkpt>
+ </trkseg>
+ </trk>
+</gpx> \ No newline at end of file
diff --git a/res/raw/u1n.gpx b/res/raw/u1n.gpx
new file mode 100644
index 0000000..796577d
--- /dev/null
+++ b/res/raw/u1n.gpx
@@ -0,0 +1,374 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
+ <metadata>
+ <author>
+ <name>chrisb8</name>
+ </author>
+ <copyright author="chrisb8">
+ <year>2012</year>
+ <license>http://creativecommons.org/licenses/by-sa/2.5</license>
+ </copyright>
+ <bounds minlat="50.896579" minlon="-1.4117661" maxlat="50.9497302" maxlon="-1.3636415" />
+ </metadata>
+ <trk> <trkseg>
+ <trkpt lat="50.90311809839727" lon="-1.4117660660970894">
+ </trkpt>
+ <trkpt lat="50.90280511769825" lon="-1.4113706172395304">
+ </trkpt>
+ <trkpt lat="50.90248856202004" lon="-1.4110204920332676">
+ </trkpt>
+ <trkpt lat="50.90219129784353" lon="-1.4107179566608656">
+ </trkpt>
+ <trkpt lat="50.90189760468991" lon="-1.4104380831141121">
+ </trkpt>
+ <trkpt lat="50.9015967637967" lon="-1.4101763390278768">
+ </trkpt>
+ <trkpt lat="50.90128591665141" lon="-1.4099123287590765">
+ </trkpt>
+ <trkpt lat="50.90090904478925" lon="-1.4096197162741697">
+ </trkpt>
+ <trkpt lat="50.90064964451786" lon="-1.4093749685571704">
+ </trkpt>
+ <trkpt lat="50.90037666526121" lon="-1.4091347532053005">
+ </trkpt>
+ <trkpt lat="50.90012512274929" lon="-1.4089160665877962">
+ </trkpt>
+ <trkpt lat="50.89976424262455" lon="-1.4086146643066773">
+ </trkpt>
+ <trkpt lat="50.89945052475844" lon="-1.4083585856768537">
+ </trkpt>
+ <trkpt lat="50.89913823403168" lon="-1.408104773229595">
+ </trkpt>
+ <trkpt lat="50.89888850507473" lon="-1.4079279661887882">
+ </trkpt>
+ <trkpt lat="50.89881132493647" lon="-1.407835052703631">
+ </trkpt>
+ <trkpt lat="50.89878559819529" lon="-1.4077330744882146">
+ </trkpt>
+ <trkpt lat="50.898768447026605" lon="-1.4076378948204926">
+ </trkpt>
+ <trkpt lat="50.898716993482644" lon="-1.4075540460655946">
+ </trkpt>
+ <trkpt lat="50.8986555350084" lon="-1.4074951253189099">
+ </trkpt>
+ <trkpt lat="50.898588359374" lon="-1.407476995858391">
+ </trkpt>
+ <trkpt lat="50.898514037282595" lon="-1.407467931128132">
+ </trkpt>
+ <trkpt lat="50.8983839733372" lon="-1.4074724634932614">
+ </trkpt>
+ <trkpt lat="50.898278206784106" lon="-1.4074588663978729">
+ </trkpt>
+ <trkpt lat="50.89811955650403" lon="-1.4073614205475862">
+ </trkpt>
+ <trkpt lat="50.89797662786095" lon="-1.4072481114193454">
+ </trkpt>
+ <trkpt lat="50.89780082502831" lon="-1.4070441549885127">
+ </trkpt>
+ <trkpt lat="50.89759357693419" lon="-1.406790342541254">
+ </trkpt>
+ <trkpt lat="50.89737632276942" lon="-1.4064436166088383">
+ </trkpt>
+ <trkpt lat="50.897084963803245" lon="-1.4058610190047827">
+ </trkpt>
+ <trkpt lat="50.89674192670159" lon="-1.405113178758396">
+ </trkpt>
+ <trkpt lat="50.89657898319309" lon="-1.4047369924526378">
+ </trkpt>
+ <trkpt lat="50.89660185249183" lon="-1.404650877515175">
+ </trkpt>
+ <trkpt lat="50.89675105263081" lon="-1.4045174005066738">
+ </trkpt>
+ <trkpt lat="50.896890527128264" lon="-1.40439721802725">
+ </trkpt>
+ <trkpt lat="50.89888456248814" lon="-1.4039837902980319">
+ </trkpt>
+ <trkpt lat="50.89950307004378" lon="-1.403961356235206">
+ </trkpt>
+ <trkpt lat="50.900150877155276" lon="-1.4040030194947395">
+ </trkpt>
+ <trkpt lat="50.900173774449506" lon="-1.4040373815097085">
+ </trkpt>
+ <trkpt lat="50.90015447995951" lon="-1.4046707795365723">
+ </trkpt>
+ <trkpt lat="50.90026167146941" lon="-1.4048384770463684">
+ </trkpt>
+ <trkpt lat="50.90040316388463" lon="-1.4048702036022755">
+ </trkpt>
+ <trkpt lat="50.90114992228657" lon="-1.4049166603448544">
+ </trkpt>
+ <trkpt lat="50.90160368828852" lon="-1.4051036204064504">
+ </trkpt>
+ <trkpt lat="50.902366148131826" lon="-1.405607846027121">
+ </trkpt>
+ <trkpt lat="50.90272272066198" lon="-1.4057234213379264">
+ </trkpt>
+ <trkpt lat="50.90315717809011" lon="-1.4059341763164535">
+ </trkpt>
+ <trkpt lat="50.90408538851817" lon="-1.4062061182242316">
+ </trkpt>
+ <trkpt lat="50.90528010172193" lon="-1.4064712615843145">
+ </trkpt>
+ <trkpt lat="50.906081085451476" lon="-1.4066990129320776">
+ </trkpt>
+ <trkpt lat="50.9067113682861" lon="-1.4067952199029732">
+ </trkpt>
+ <trkpt lat="50.90690739907103" lon="-1.4066830495888443">
+ </trkpt>
+ <trkpt lat="50.90708726164237" lon="-1.4065772890069514">
+ </trkpt>
+ <trkpt lat="50.90706907332404" lon="-1.406042076365251">
+ </trkpt>
+ <trkpt lat="50.90703471759225" lon="-1.4047184666585317">
+ </trkpt>
+ <trkpt lat="50.91029531880754" lon="-1.4049632224688342">
+ </trkpt>
+ <trkpt lat="50.910511083790915" lon="-1.4049836181119173">
+ </trkpt>
+ <trkpt lat="50.910761141295204" lon="-1.4050028806637178">
+ </trkpt>
+ <trkpt lat="50.911021914118685" lon="-1.4047943918677555">
+ </trkpt>
+ <trkpt lat="50.91133912621388" lon="-1.404542845603062">
+ </trkpt>
+ <trkpt lat="50.91253936862984" lon="-1.4034426139678475">
+ </trkpt>
+ <trkpt lat="50.91245363805515" lon="-1.4029542516251317">
+ </trkpt>
+ <trkpt lat="50.91229860819828" lon="-1.4019899909438054">
+ </trkpt>
+ <trkpt lat="50.911570677245" lon="-1.4021949527683772">
+ </trkpt>
+ <trkpt lat="50.91084522980175" lon="-1.4024801858528766">
+ </trkpt>
+ <trkpt lat="50.91069165173404" lon="-1.401852032093755">
+ </trkpt>
+ <trkpt lat="50.910699734802854" lon="-1.4017110179845644">
+ </trkpt>
+ <trkpt lat="50.91075227471603" lon="-1.4016052574026718">
+ </trkpt>
+ <trkpt lat="50.910883624239496" lon="-1.401499496820779">
+ </trkpt>
+ <trkpt lat="50.91100486962448" lon="-1.4013488681132347">
+ </trkpt>
+ <trkpt lat="50.91106145069605" lon="-1.4011597810122747">
+ </trkpt>
+ <trkpt lat="50.91105538844166" lon="-1.400845704132714">
+ </trkpt>
+ <trkpt lat="50.911045284682615" lon="-1.4004643250646762">
+ </trkpt>
+ <trkpt lat="50.91105538844166" lon="-1.4002367795703003">
+ </trkpt>
+ <trkpt lat="50.91110186570506" lon="-1.4000412827371045">
+ </trkpt>
+ <trkpt lat="50.91115844665871" lon="-1.399839376171673">
+ </trkpt>
+ <trkpt lat="50.91183539201999" lon="-1.399941931887448">
+ </trkpt>
+ <trkpt lat="50.91254120602011" lon="-1.4001472548952145">
+ </trkpt>
+ <trkpt lat="50.915463027824224" lon="-1.397198778066687">
+ </trkpt>
+ <trkpt lat="50.91580046015862" lon="-1.3967244578812277">
+ </trkpt>
+ <trkpt lat="50.916420763516065" lon="-1.3962341133651792">
+ </trkpt>
+ <trkpt lat="50.917245127820486" lon="-1.395721334786305">
+ </trkpt>
+ <trkpt lat="50.91913222053742" lon="-1.3954200773712162">
+ </trkpt>
+ <trkpt lat="50.919992903366115" lon="-1.395484174693575">
+ </trkpt>
+ <trkpt lat="50.92191220914427" lon="-1.3955258379531088">
+ </trkpt>
+ <trkpt lat="50.922536471538784" lon="-1.3955354525514627">
+ </trkpt>
+ <trkpt lat="50.9230051678961" lon="-1.3954136676389801">
+ </trkpt>
+ <trkpt lat="50.92395466759648" lon="-1.394724621423618">
+ </trkpt>
+ <trkpt lat="50.924602080104556" lon="-1.3940364471816222">
+ </trkpt>
+ <trkpt lat="50.92451925333141" lon="-1.3938313357500722">
+ </trkpt>
+ <trkpt lat="50.925636392267634" lon="-1.3926519450186612">
+ </trkpt>
+ <trkpt lat="50.925939409053754" lon="-1.3923250486746288">
+ </trkpt>
+ <trkpt lat="50.926440392477545" lon="-1.3915430613418451">
+ </trkpt>
+ <trkpt lat="50.92688884886917" lon="-1.390847605394247">
+ </trkpt>
+ <trkpt lat="50.92709489495093" lon="-1.3908540151264828">
+ </trkpt>
+ <trkpt lat="50.92731710048689" lon="-1.391366793705357">
+ </trkpt>
+ <trkpt lat="50.92909874649975" lon="-1.390696976686703">
+ </trkpt>
+ <trkpt lat="50.929735032109505" lon="-1.3905687820419839">
+ </trkpt>
+ <trkpt lat="50.93028243276415" lon="-1.390565577175866">
+ </trkpt>
+ <trkpt lat="50.93105605443761" lon="-1.3907033864189384">
+ </trkpt>
+ <trkpt lat="50.93157112178446" lon="-1.3930108900238736">
+ </trkpt>
+ <trkpt lat="50.93228614699877" lon="-1.3951389211262024">
+ </trkpt>
+ <trkpt lat="50.93344349502364" lon="-1.3955940121149537">
+ </trkpt>
+ <trkpt lat="50.93422312335655" lon="-1.3961580685517154">
+ </trkpt>
+ <trkpt lat="50.934471551400726" lon="-1.3962990826609059">
+ </trkpt>
+ <trkpt lat="50.93478460924134" lon="-1.3963439507865574">
+ </trkpt>
+ <trkpt lat="50.93562135270211" lon="-1.3960468566528774">
+ </trkpt>
+ <trkpt lat="50.935694068040966" lon="-1.396042818163723">
+ </trkpt>
+ <trkpt lat="50.935740040102765" lon="-1.3960472844476772">
+ </trkpt>
+ <trkpt lat="50.93573862167796" lon="-1.396191256383319">
+ </trkpt>
+ <trkpt lat="50.93575071280244" lon="-1.3963231305799246">
+ </trkpt>
+ <trkpt lat="50.93578137729115" lon="-1.3963901111306434">
+ </trkpt>
+ <trkpt lat="50.936110199640964" lon="-1.3964980656492487">
+ </trkpt>
+ <trkpt lat="50.936469103199684" lon="-1.397050429508146">
+ </trkpt>
+ <trkpt lat="50.93705219407009" lon="-1.397174448836574">
+ </trkpt>
+ <trkpt lat="50.937113665255985" lon="-1.3961919634026223">
+ </trkpt>
+ <trkpt lat="50.937849811033644" lon="-1.3963120615634608">
+ </trkpt>
+ <trkpt lat="50.93790292420903" lon="-1.396287054809716">
+ </trkpt>
+ <trkpt lat="50.93795111314548" lon="-1.3961711090580617">
+ </trkpt>
+ <trkpt lat="50.937975258588594" lon="-1.396040844484428">
+ </trkpt>
+ <trkpt lat="50.93803142350603" lon="-1.395474847531945">
+ </trkpt>
+ <trkpt lat="50.93813203405495" lon="-1.3945296227522113">
+ </trkpt>
+ <trkpt lat="50.93828578714404" lon="-1.3929796128051273">
+ </trkpt>
+ <trkpt lat="50.93837289411554" lon="-1.3920029477201357">
+ </trkpt>
+ <trkpt lat="50.93846579402947" lon="-1.3907902677964246">
+ </trkpt>
+ <trkpt lat="50.93853496020105" lon="-1.389840832163797">
+ </trkpt>
+ <trkpt lat="50.9385743340668" lon="-1.3891882800068518">
+ </trkpt>
+ <trkpt lat="50.93854455685456" lon="-1.3884291481870266">
+ </trkpt>
+ <trkpt lat="50.93850087826561" lon="-1.3873070474148834">
+ </trkpt>
+ <trkpt lat="50.93845492950492" lon="-1.3861941636102395">
+ </trkpt>
+ <trkpt lat="50.938388785056475" lon="-1.3845877304234286">
+ </trkpt>
+ <trkpt lat="50.938384996496346" lon="-1.384484427084498">
+ </trkpt>
+ <trkpt lat="50.93837470814106" lon="-1.3844275585753623">
+ </trkpt>
+ <trkpt lat="50.93821595895049" lon="-1.3841039385552794">
+ </trkpt>
+ <trkpt lat="50.93755981391343" lon="-1.3827482087295484">
+ </trkpt>
+ <trkpt lat="50.93681834896983" lon="-1.3812206566645666">
+ </trkpt>
+ <trkpt lat="50.936609795139226" lon="-1.380553623061897">
+ </trkpt>
+ <trkpt lat="50.936616871390676" lon="-1.3799658920311901">
+ </trkpt>
+ <trkpt lat="50.93661861999296" lon="-1.378871475398375">
+ </trkpt>
+ <trkpt lat="50.936661710292846" lon="-1.3781217810317532">
+ </trkpt>
+ <trkpt lat="50.936925866439736" lon="-1.3779398688270936">
+ </trkpt>
+ <trkpt lat="50.937115071752565" lon="-1.3776199420932513">
+ </trkpt>
+ <trkpt lat="50.937314178510846" lon="-1.3769174713176366">
+ </trkpt>
+ <trkpt lat="50.93751472065079" lon="-1.3759329626641739">
+ </trkpt>
+ <trkpt lat="50.93762091378214" lon="-1.3757762737203671">
+ </trkpt>
+ <trkpt lat="50.93906992124842" lon="-1.3757347546706975">
+ </trkpt>
+ <trkpt lat="50.93963701585826" lon="-1.3757140782794803">
+ </trkpt>
+ <trkpt lat="50.940098517143966" lon="-1.3755822240816804">
+ </trkpt>
+ <trkpt lat="50.940350633034996" lon="-1.3754565002108357">
+ </trkpt>
+ <trkpt lat="50.94045810371675" lon="-1.3754582268106252">
+ </trkpt>
+ <trkpt lat="50.9409138249962" lon="-1.3757520819859324">
+ </trkpt>
+ <trkpt lat="50.94097972289687" lon="-1.3757546048216054">
+ </trkpt>
+ <trkpt lat="50.941485051432835" lon="-1.375181782084171">
+ </trkpt>
+ <trkpt lat="50.94212950711594" lon="-1.3745843519442114">
+ </trkpt>
+ <trkpt lat="50.94209744468576" lon="-1.3739323220236273">
+ </trkpt>
+ <trkpt lat="50.942067153621984" lon="-1.37351889429441">
+ </trkpt>
+ <trkpt lat="50.942186298358976" lon="-1.3728875356691705">
+ </trkpt>
+ <trkpt lat="50.94228928763135" lon="-1.3727048583004466">
+ </trkpt>
+ <trkpt lat="50.943062709583174" lon="-1.3717145546699954">
+ </trkpt>
+ <trkpt lat="50.943787654769714" lon="-1.3707819386296676">
+ </trkpt>
+ <trkpt lat="50.94442979733195" lon="-1.369961492903468">
+ </trkpt>
+ <trkpt lat="50.94509616231102" lon="-1.369169890972331">
+ </trkpt>
+ <trkpt lat="50.94561713191443" lon="-1.3685545566776816">
+ </trkpt>
+ <trkpt lat="50.94636626789319" lon="-1.367714881754775">
+ </trkpt>
+ <trkpt lat="50.94694174151074" lon="-1.3670899328617718">
+ </trkpt>
+ <trkpt lat="50.947604032154835" lon="-1.3661156535619103">
+ </trkpt>
+ <trkpt lat="50.947923059036654" lon="-1.365452246275491">
+ </trkpt>
+ <trkpt lat="50.94810276308832" lon="-1.3651413742620486">
+ </trkpt>
+ <trkpt lat="50.9480967056597" lon="-1.3647375611311847">
+ </trkpt>
+ <trkpt lat="50.94799171010469" lon="-1.3645036059045734">
+ </trkpt>
+ <trkpt lat="50.94800988242926" lon="-1.3643305431342034">
+ </trkpt>
+ <trkpt lat="50.94811487794322" lon="-1.3641959387572486">
+ </trkpt>
+ <trkpt lat="50.948369289166536" lon="-1.364080563577002">
+ </trkpt>
+ <trkpt lat="50.94871455931386" lon="-1.3639619835306374">
+ </trkpt>
+ <trkpt lat="50.94903963588043" lon="-1.3638530180826267">
+ </trkpt>
+ <trkpt lat="50.94923952655344" lon="-1.3638722472793343">
+ </trkpt>
+ <trkpt lat="50.94943537819729" lon="-1.3638017402247389">
+ </trkpt>
+ <trkpt lat="50.94973016365181" lon="-1.3636414969188408">
+ </trkpt>
+ </trkseg>
+ </trk>
+</gpx> \ No newline at end of file
diff --git a/res/raw/u2.gpx b/res/raw/u2.gpx
new file mode 100644
index 0000000..a9075cf
--- /dev/null
+++ b/res/raw/u2.gpx
@@ -0,0 +1,399 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
+ <metadata>
+ <author>
+ <name>chrisb8</name>
+ </author>
+ <copyright author="chrisb8">
+ <year>2012</year>
+ <license>http://creativecommons.org/licenses/by-sa/2.5</license>
+ </copyright>
+ <bounds minlat="50.9069747" minlon="-1.4085664" maxlat="50.9520169" maxlon="-1.3879651" />
+ </metadata>
+ <trk> <trkseg>
+ <trkpt lat="50.93641251817192" lon="-1.3971626985182617">
+ </trkpt>
+ <trkpt lat="50.937115483272656" lon="-1.39728973948407">
+ </trkpt>
+ <trkpt lat="50.93718025269314" lon="-1.39642238764144">
+ </trkpt>
+ <trkpt lat="50.937836804121794" lon="-1.3965468621946984">
+ </trkpt>
+ <trkpt lat="50.93789606613078" lon="-1.3967237180162608">
+ </trkpt>
+ <trkpt lat="50.93794736751038" lon="-1.3971490141585856">
+ </trkpt>
+ <trkpt lat="50.93789812164837" lon="-1.3982098014790418">
+ </trkpt>
+ <trkpt lat="50.93781767245492" lon="-1.3993813398799415">
+ </trkpt>
+ <trkpt lat="50.941706327503155" lon="-1.4012348470517824">
+ </trkpt>
+ <trkpt lat="50.941083681408415" lon="-1.398259177673137">
+ </trkpt>
+ <trkpt lat="50.94090679179239" lon="-1.397540525445841">
+ </trkpt>
+ <trkpt lat="50.94056716184317" lon="-1.3971362835679875">
+ </trkpt>
+ <trkpt lat="50.94014969663178" lon="-1.3949803268861005">
+ </trkpt>
+ <trkpt lat="50.940008182150144" lon="-1.3943515061872171">
+ </trkpt>
+ <trkpt lat="50.93971807611633" lon="-1.3936440829009726">
+ </trkpt>
+ <trkpt lat="50.939024644604" lon="-1.393486877726252">
+ </trkpt>
+ <trkpt lat="50.9390883275211" lon="-1.3924875019726688">
+ </trkpt>
+ <trkpt lat="50.93927937574898" lon="-1.3894669168298173">
+ </trkpt>
+ <trkpt lat="50.939675621422936" lon="-1.389444458947714">
+ </trkpt>
+ <trkpt lat="50.940001106414776" lon="-1.3888605540130365">
+ </trkpt>
+ <trkpt lat="50.940213378008" lon="-1.3888830118951387">
+ </trkpt>
+ <trkpt lat="50.940510556610434" lon="-1.388624746250955">
+ </trkpt>
+ <trkpt lat="50.94092792707352" lon="-1.3885090026851705">
+ </trkpt>
+ <trkpt lat="50.94248639810336" lon="-1.388219190481919">
+ </trkpt>
+ <trkpt lat="50.944032309727646" lon="-1.387965108550301">
+ </trkpt>
+ <trkpt lat="50.94444254301676" lon="-1.3896087010454539">
+ </trkpt>
+ <trkpt lat="50.94463264989889" lon="-1.3901168649086892">
+ </trkpt>
+ <trkpt lat="50.94491780876443" lon="-1.3905853284701095">
+ </trkpt>
+ <trkpt lat="50.94630355589115" lon="-1.3925862236815991">
+ </trkpt>
+ <trkpt lat="50.94708427456096" lon="-1.3938410070036853">
+ </trkpt>
+ <trkpt lat="50.94747768953388" lon="-1.3944924325282022">
+ </trkpt>
+ <trkpt lat="50.94805368758857" lon="-1.395787611934612">
+ </trkpt>
+ <trkpt lat="50.94869177508018" lon="-1.39722476977782">
+ <time>2006-05-11T21:32:17Z</time>
+ </trkpt>
+ <trkpt lat="50.949358475043255" lon="-1.3993452697778201">
+ <time>2006-10-06T23:46:15Z</time>
+ </trkpt>
+ <trkpt lat="50.94966027502651" lon="-1.4001624697778197">
+ <time>2008-12-01T15:56:19Z</time>
+ </trkpt>
+ <trkpt lat="50.950259374993294" lon="-1.4012715697778202">
+ <time>2006-05-11T21:32:17Z</time>
+ </trkpt>
+ <trkpt lat="50.95081167496269" lon="-1.4020943697778199">
+ <time>2006-10-06T23:46:15Z</time>
+ </trkpt>
+ <trkpt lat="50.95152087492341" lon="-1.40292406977782">
+ <time>2006-10-06T23:46:16Z</time>
+ </trkpt>
+ <trkpt lat="50.95192217490119" lon="-1.40321646977782">
+ <time>2010-09-15T18:46:10Z</time>
+ </trkpt>
+ <trkpt lat="50.95201687489595" lon="-1.4034524697778195">
+ <time>2010-09-15T18:46:11Z</time>
+ </trkpt>
+ <trkpt lat="50.95198977489744" lon="-1.4037636697778195">
+ <time>2010-09-15T18:46:12Z</time>
+ </trkpt>
+ <trkpt lat="50.951820874906794" lon="-1.4039674697778197">
+ <time>2010-09-15T18:46:12Z</time>
+ </trkpt>
+ <trkpt lat="50.95159777491916" lon="-1.4041820697778205">
+ <time>2010-09-15T18:46:12Z</time>
+ </trkpt>
+ <trkpt lat="50.95037997498663" lon="-1.4044830697778194">
+ <time>2009-09-11T20:15:15Z</time>
+ </trkpt>
+ <trkpt lat="50.94652577520015" lon="-1.4054466697778198">
+ <time>2010-12-14T20:31:10Z</time>
+ </trkpt>
+ <trkpt lat="50.9460280123738" lon="-1.4055375007863116">
+ </trkpt>
+ <trkpt lat="50.946074204313206" lon="-1.4050954574564833">
+ </trkpt>
+ <trkpt lat="50.9460728457274" lon="-1.4047720111175852">
+ </trkpt>
+ <trkpt lat="50.9459206838668" lon="-1.4044270016894267">
+ </trkpt>
+ <trkpt lat="50.94550668163503" lon="-1.4038615890183461">
+ </trkpt>
+ <trkpt lat="50.9448953065511" lon="-1.4034648281759639">
+ </trkpt>
+ <trkpt lat="50.94433681656947" lon="-1.4035834142761667">
+ </trkpt>
+ <trkpt lat="50.943650700047186" lon="-1.403652416161798">
+ </trkpt>
+ <trkpt lat="50.943200676296264" lon="-1.4036372585235084">
+ </trkpt>
+ <trkpt lat="50.942687096291785" lon="-1.4034475033380212">
+ </trkpt>
+ <trkpt lat="50.94214361920932" lon="-1.4026453564175527">
+ </trkpt>
+ <trkpt lat="50.9416680715507" lon="-1.4014291981832947">
+ </trkpt>
+ <trkpt lat="50.94076859382156" lon="-1.4009159966589093">
+ </trkpt>
+ <trkpt lat="50.93949135989852" lon="-1.4003294806310407">
+ </trkpt>
+ <trkpt lat="50.93781653312083" lon="-1.399382945667083">
+ </trkpt>
+ <trkpt lat="50.93785924758087" lon="-1.3987637805086004">
+ </trkpt>
+ <trkpt lat="50.937949843169484" lon="-1.397144811055968">
+ </trkpt>
+ <trkpt lat="50.93792016180973" lon="-1.3969286790696627">
+ </trkpt>
+ <trkpt lat="50.93789956072803" lon="-1.3967210466056597">
+ </trkpt>
+ <trkpt lat="50.93783087237752" lon="-1.3965399587091176">
+ </trkpt>
+ <trkpt lat="50.937174499233855" lon="-1.3964219916724367">
+ </trkpt>
+ <trkpt lat="50.935787692312005" lon="-1.3961831899524508">
+ </trkpt>
+ <trkpt lat="50.93564764449113" lon="-1.3961693671249324">
+ </trkpt>
+ <trkpt lat="50.93566381109717" lon="-1.3963893393549478">
+ </trkpt>
+ <trkpt lat="50.93574783515405" lon="-1.396522593908596">
+ </trkpt>
+ <trkpt lat="50.936060472159355" lon="-1.3966203835648714">
+ </trkpt>
+ <trkpt lat="50.93641313789939" lon="-1.3971638751791782">
+ </trkpt>
+ <trkpt lat="50.93711461591232" lon="-1.397291951862064">
+ </trkpt>
+ <trkpt lat="50.93718128894593" lon="-1.3964238349129183">
+ </trkpt>
+ <trkpt lat="50.937830416176986" lon="-1.3965480574210472">
+ </trkpt>
+ <trkpt lat="50.937891508924764" lon="-1.3967238497851118">
+ </trkpt>
+ <trkpt lat="50.93795155122028" lon="-1.397148643014535">
+ </trkpt>
+ <trkpt lat="50.93790669002525" lon="-1.3980636327036113">
+ </trkpt>
+ <trkpt lat="50.937816721989314" lon="-1.39938255095633">
+ </trkpt>
+ <trkpt lat="50.93773811670514" lon="-1.3997292191510156">
+ </trkpt>
+ <trkpt lat="50.937253760771206" lon="-1.4014216595743372">
+ </trkpt>
+ <trkpt lat="50.936935281366424" lon="-1.4026536181251579">
+ </trkpt>
+ <trkpt lat="50.93663800692334" lon="-1.4037994339672453">
+ </trkpt>
+ <trkpt lat="50.93650753842413" lon="-1.4041283501739412">
+ </trkpt>
+ <trkpt lat="50.935886413677125" lon="-1.4064464258098563">
+ </trkpt>
+ <trkpt lat="50.93455507719845" lon="-1.4062987852559161">
+ </trkpt>
+ <trkpt lat="50.93028064944775" lon="-1.4059013828957987">
+ </trkpt>
+ <trkpt lat="50.927554981155644" lon="-1.4056197140680324">
+ </trkpt>
+ <trkpt lat="50.92434092614129" lon="-1.4053597826321358">
+ </trkpt>
+ <trkpt lat="50.923255122351826" lon="-1.405299689248065">
+ </trkpt>
+ <trkpt lat="50.921924834480755" lon="-1.4050817819740073">
+ </trkpt>
+ <trkpt lat="50.92038330388033" lon="-1.4047340054185753">
+ </trkpt>
+ <trkpt lat="50.91896529418007" lon="-1.4040407321591755">
+ </trkpt>
+ <trkpt lat="50.918617076316224" lon="-1.403681103932821">
+ </trkpt>
+ <trkpt lat="50.91849819312757" lon="-1.4035461229066486">
+ </trkpt>
+ <trkpt lat="50.918316966133474" lon="-1.4034110476884332">
+ </trkpt>
+ <trkpt lat="50.91758709790006" lon="-1.403043024342412">
+ </trkpt>
+ <trkpt lat="50.91689422144276" lon="-1.4027308029187173">
+ </trkpt>
+ <trkpt lat="50.915643006707235" lon="-1.4022047340517072">
+ </trkpt>
+ <trkpt lat="50.914668740595246" lon="-1.4013884115029893">
+ </trkpt>
+ <trkpt lat="50.91449167591715" lon="-1.4013094224768479">
+ </trkpt>
+ <trkpt lat="50.91432472303023" lon="-1.4013440544745386">
+ </trkpt>
+ <trkpt lat="50.914240508654245" lon="-1.4014221567595324">
+ </trkpt>
+ <trkpt lat="50.914184839103264" lon="-1.4015473016340478">
+ </trkpt>
+ <trkpt lat="50.91416261036937" lon="-1.4017567054046363">
+ </trkpt>
+ <trkpt lat="50.91390259754488" lon="-1.4018727551851347">
+ </trkpt>
+ <trkpt lat="50.913829381048735" lon="-1.4019908160974606">
+ </trkpt>
+ <trkpt lat="50.913425025107735" lon="-1.4026090331173022">
+ </trkpt>
+ <trkpt lat="50.91301844601484" lon="-1.4029373774485445">
+ </trkpt>
+ <trkpt lat="50.91245607495282" lon="-1.403431538915836">
+ </trkpt>
+ <trkpt lat="50.91131105078747" lon="-1.4044829706901936">
+ </trkpt>
+ <trkpt lat="50.91075658832449" lon="-1.4049337973274272">
+ </trkpt>
+ <trkpt lat="50.91068401636802" lon="-1.4049309900921645">
+ </trkpt>
+ <trkpt lat="50.91058312346001" lon="-1.4049253756216387">
+ </trkpt>
+ <trkpt lat="50.91052834727436" lon="-1.404989255891379">
+ </trkpt>
+ <trkpt lat="50.91043974895135" lon="-1.4052285570300287">
+ </trkpt>
+ <trkpt lat="50.90973880055169" lon="-1.4079992982344847">
+ </trkpt>
+ <trkpt lat="50.9096396756837" lon="-1.4083193230544524">
+ </trkpt>
+ <trkpt lat="50.90954386709504" lon="-1.4084819923123926">
+ </trkpt>
+ <trkpt lat="50.909391862590084" lon="-1.4085579380517965">
+ </trkpt>
+ <trkpt lat="50.9092449442045" lon="-1.4085663597575857">
+ </trkpt>
+ <trkpt lat="50.909105105792335" lon="-1.4085326729344307">
+ </trkpt>
+ <trkpt lat="50.908961726730965" lon="-1.4084765282291731">
+ </trkpt>
+ <trkpt lat="50.908506805057165" lon="-1.4082884434665608">
+ </trkpt>
+ <trkpt lat="50.907490738260805" lon="-1.4077157674729344">
+ </trkpt>
+ <trkpt lat="50.90727477695493" lon="-1.407451887358225">
+ </trkpt>
+ <trkpt lat="50.907111818850815" lon="-1.4070897291009066">
+ </trkpt>
+ <trkpt lat="50.907041273441266" lon="-1.4068530337968004">
+ </trkpt>
+ <trkpt lat="50.90702180137332" lon="-1.406547045153147">
+ </trkpt>
+ <trkpt lat="50.90697474435779" lon="-1.4046253255689387">
+ </trkpt>
+ <trkpt lat="50.91029438956286" lon="-1.4048921816531188">
+ </trkpt>
+ <trkpt lat="50.91053002184162" lon="-1.4049141466805866">
+ </trkpt>
+ <trkpt lat="50.910581353407025" lon="-1.4049197611511126">
+ </trkpt>
+ <trkpt lat="50.9107584123077" lon="-1.4049298088300026">
+ </trkpt>
+ <trkpt lat="50.91130869696468" lon="-1.4044857283540604">
+ </trkpt>
+ <trkpt lat="50.912454031811215" lon="-1.4034319264617896">
+ </trkpt>
+ <trkpt lat="50.91302555066173" lon="-1.402921515130758">
+ </trkpt>
+ <trkpt lat="50.91342701479007" lon="-1.402607210768717">
+ </trkpt>
+ <trkpt lat="50.91369951341767" lon="-1.4024679302122536">
+ </trkpt>
+ <trkpt lat="50.9140440199003" lon="-1.4024126792898228">
+ </trkpt>
+ <trkpt lat="50.914273022556735" lon="-1.4024180227912568">
+ </trkpt>
+ <trkpt lat="50.915173698909186" lon="-1.4026679530608652">
+ </trkpt>
+ <trkpt lat="50.916328208716834" lon="-1.4030657492546847">
+ </trkpt>
+ <trkpt lat="50.91713289178791" lon="-1.4033932767446606">
+ </trkpt>
+ <trkpt lat="50.91851140339892" lon="-1.4039496267601075">
+ </trkpt>
+ <trkpt lat="50.91896817672318" lon="-1.4040409217174796">
+ </trkpt>
+ <trkpt lat="50.92038507356052" lon="-1.4047340054185753">
+ </trkpt>
+ <trkpt lat="50.921932220847594" lon="-1.405088116069832">
+ </trkpt>
+ <trkpt lat="50.92324450492464" lon="-1.405299689248065">
+ </trkpt>
+ <trkpt lat="50.92435283091402" lon="-1.4053600188821962">
+ </trkpt>
+ <trkpt lat="50.92822212645253" lon="-1.4056919839006947">
+ </trkpt>
+ <trkpt lat="50.928314208718724" lon="-1.4044856801595997">
+ </trkpt>
+ <trkpt lat="50.928624283329924" lon="-1.4040944680910348">
+ </trkpt>
+ <trkpt lat="50.92929563964123" lon="-1.4036834819738084">
+ </trkpt>
+ <trkpt lat="50.92985957097451" lon="-1.4034205999782379">
+ </trkpt>
+ <trkpt lat="50.93015611909006" lon="-1.403321021365759">
+ </trkpt>
+ <trkpt lat="50.93063888221971" lon="-1.4030400147277224">
+ </trkpt>
+ <trkpt lat="50.931010235063624" lon="-1.4029357703297414">
+ </trkpt>
+ <trkpt lat="50.93126446722398" lon="-1.4028496553922791">
+ </trkpt>
+ <trkpt lat="50.93168151921898" lon="-1.4027227491686494">
+ </trkpt>
+ <trkpt lat="50.932021442393875" lon="-1.4025913105798908">
+ </trkpt>
+ <trkpt lat="50.93228502425437" lon="-1.402347039802899">
+ </trkpt>
+ <trkpt lat="50.932647008802576" lon="-1.4029946910764268">
+ </trkpt>
+ <trkpt lat="50.93308404335585" lon="-1.4040054085003315">
+ </trkpt>
+ <trkpt lat="50.93358105805294" lon="-1.4050070611939767">
+ </trkpt>
+ <trkpt lat="50.93455140942648" lon="-1.4062982227895295">
+ </trkpt>
+ <trkpt lat="50.93588731408788" lon="-1.4064459461692094">
+ </trkpt>
+ <trkpt lat="50.9365075384241" lon="-1.404129483265224">
+ </trkpt>
+ <trkpt lat="50.93663884348589" lon="-1.4037963901537636">
+ </trkpt>
+ <trkpt lat="50.93693506299182" lon="-1.4026520453358506">
+ </trkpt>
+ <trkpt lat="50.937256433339364" lon="-1.4014211916508807">
+ </trkpt>
+ <trkpt lat="50.93773566869515" lon="-1.3997308564304882">
+ </trkpt>
+ <trkpt lat="50.93781833836264" lon="-1.3993808817966862">
+ </trkpt>
+ <trkpt lat="50.93790740405658" lon="-1.3980658988861763">
+ </trkpt>
+ <trkpt lat="50.937951302846734" lon="-1.3971506384345151">
+ </trkpt>
+ <trkpt lat="50.9378936657" lon="-1.3967222032141058">
+ </trkpt>
+ <trkpt lat="50.93783550951212" lon="-1.3965478081812854">
+ </trkpt>
+ <trkpt lat="50.93718157539937" lon="-1.3964219916724374">
+ </trkpt>
+ <trkpt lat="50.93579299959451" lon="-1.3961831899524508">
+ </trkpt>
+ <trkpt lat="50.935647460690376" lon="-1.3961704388303628">
+ </trkpt>
+ <trkpt lat="50.935664632783656" lon="-1.3963924871649571">
+ </trkpt>
+ <trkpt lat="50.935747571707495" lon="-1.3965209797614928">
+ </trkpt>
+ <trkpt lat="50.93605817686309" lon="-1.3966185602482426">
+ </trkpt>
+ <trkpt lat="50.93641251817192" lon="-1.3971626985182617">
+ </trkpt>
+ </trkseg>
+ </trk>
+</gpx> \ No newline at end of file
diff --git a/res/raw/u6.gpx b/res/raw/u6.gpx
new file mode 100644
index 0000000..5356358
--- /dev/null
+++ b/res/raw/u6.gpx
@@ -0,0 +1,750 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
+ <metadata>
+ <author>
+ <name>chrisb8</name>
+ </author>
+ <copyright author="chrisb8">
+ <year>2012</year>
+ <license>http://creativecommons.org/licenses/by-sa/2.5</license>
+ </copyright>
+ <bounds minlat="50.8931641" minlon="-1.436123" maxlat="50.9422177" maxlon="-1.3747638" />
+ </metadata>
+ <trk> <trkseg>
+ <trkpt lat="50.93707060759229" lon="-1.3965419716441054">
+ </trkpt>
+ <trkpt lat="50.937076460936126" lon="-1.3962656384569174">
+ </trkpt>
+ <trkpt lat="50.93784430496908" lon="-1.3963913178990814">
+ </trkpt>
+ <trkpt lat="50.93793555283888" lon="-1.3964221662931373">
+ </trkpt>
+ <trkpt lat="50.93798363159425" lon="-1.3965231991720146">
+ </trkpt>
+ <trkpt lat="50.9379942385694" lon="-1.3966737728391723">
+ </trkpt>
+ <trkpt lat="50.93798123597186" lon="-1.3968470209565111">
+ </trkpt>
+ <trkpt lat="50.93798906773613" lon="-1.3971483929412563">
+ </trkpt>
+ <trkpt lat="50.93786533060717" lon="-1.3994098756289246">
+ </trkpt>
+ <trkpt lat="50.93733572835861" lon="-1.4013675991855574">
+ </trkpt>
+ <trkpt lat="50.936685409259574" lon="-1.4038449606947447">
+ </trkpt>
+ <trkpt lat="50.936554758928594" lon="-1.4041679594022989">
+ </trkpt>
+ <trkpt lat="50.93594429469434" lon="-1.406450554607488">
+ </trkpt>
+ <trkpt lat="50.940391159573004" lon="-1.406865413595758">
+ </trkpt>
+ <trkpt lat="50.940610505029234" lon="-1.4071573660630967">
+ </trkpt>
+ <trkpt lat="50.940447764951095" lon="-1.4076738973514655">
+ </trkpt>
+ <trkpt lat="50.937511270026654" lon="-1.4126258603551745">
+ </trkpt>
+ <trkpt lat="50.934426006892636" lon="-1.4186700456856747">
+ </trkpt>
+ <trkpt lat="50.93266712996252" lon="-1.4217713937311436">
+ </trkpt>
+ <trkpt lat="50.9312259297159" lon="-1.4244948344356716">
+ </trkpt>
+ <trkpt lat="50.93011008125133" lon="-1.4261227570522461">
+ </trkpt>
+ <trkpt lat="50.92891902710574" lon="-1.4287588570927805">
+ </trkpt>
+ <trkpt lat="50.93045538116225" lon="-1.4302992288032133">
+ </trkpt>
+ <trkpt lat="50.93149626973074" lon="-1.4310455944773406">
+ </trkpt>
+ <trkpt lat="50.931881592764164" lon="-1.432101622505627">
+ </trkpt>
+ <trkpt lat="50.93241703635461" lon="-1.4316569791252962">
+ </trkpt>
+ <trkpt lat="50.933152635721626" lon="-1.431490237857672">
+ </trkpt>
+ <trkpt lat="50.93376812829249" lon="-1.4314664176765826">
+ </trkpt>
+ <trkpt lat="50.934853977437776" lon="-1.433769035181869">
+ </trkpt>
+ <trkpt lat="50.93439244320183" lon="-1.4358947042027193">
+ </trkpt>
+ <trkpt lat="50.93419729052252" lon="-1.4359780748365312">
+ </trkpt>
+ <trkpt lat="50.93406218434176" lon="-1.4361229809381568">
+ </trkpt>
+ <trkpt lat="50.93397586629856" lon="-1.4358947042027193">
+ </trkpt>
+ <trkpt lat="50.934347408040836" lon="-1.4358589739310854">
+ </trkpt>
+ <trkpt lat="50.93482527891429" lon="-1.4337965432517814">
+ </trkpt>
+ <trkpt lat="50.93374336729284" lon="-1.4315531490902929">
+ </trkpt>
+ <trkpt lat="50.93315246007673" lon="-1.4315643780313445">
+ </trkpt>
+ <trkpt lat="50.932427084666415" lon="-1.4317271976765908">
+ </trkpt>
+ <trkpt lat="50.93189631500344" lon="-1.431968619909198">
+ </trkpt>
+ <trkpt lat="50.93154600370775" lon="-1.4310085454492956">
+ </trkpt>
+ <trkpt lat="50.93049859258069" lon="-1.4302281340462166">
+ </trkpt>
+ <trkpt lat="50.92902297674891" lon="-1.4287571427684709">
+ </trkpt>
+ <trkpt lat="50.93017657968975" lon="-1.4261744863266272">
+ </trkpt>
+ <trkpt lat="50.93128061460595" lon="-1.4245519043446864">
+ </trkpt>
+ <trkpt lat="50.93273138987462" lon="-1.421834500610225">
+ </trkpt>
+ <trkpt lat="50.934479337039086" lon="-1.4187353128800124">
+ </trkpt>
+ <trkpt lat="50.93611045924337" lon="-1.4158214026771496">
+ </trkpt>
+ <trkpt lat="50.937575236065015" lon="-1.4127222149469376">
+ </trkpt>
+ <trkpt lat="50.940757258789226" lon="-1.4073867750993294">
+ </trkpt>
+ <trkpt lat="50.94065819999172" lon="-1.406847785928858">
+ </trkpt>
+ <trkpt lat="50.93594752045038" lon="-1.4064456508575442">
+ </trkpt>
+ <trkpt lat="50.93655618703278" lon="-1.4041656932197342">
+ </trkpt>
+ <trkpt lat="50.93668757242949" lon="-1.403843895295531">
+ </trkpt>
+ <trkpt lat="50.93733629355833" lon="-1.4013640189781058">
+ </trkpt>
+ <trkpt lat="50.93786800342668" lon="-1.3994125690202766">
+ </trkpt>
+ <trkpt lat="50.937990077527154" lon="-1.397154802673492">
+ </trkpt>
+ <trkpt lat="50.93798366733784" lon="-1.396844230209935">
+ </trkpt>
+ <trkpt lat="50.937994635385614" lon="-1.3966698028089906">
+ </trkpt>
+ <trkpt lat="50.93798462835103" lon="-1.3965189416620918">
+ </trkpt>
+ <trkpt lat="50.93793334226491" lon="-1.396421858311969">
+ </trkpt>
+ <trkpt lat="50.93784783493955" lon="-1.3963914744055022">
+ </trkpt>
+ <trkpt lat="50.937074923088204" lon="-1.3962611847641464">
+ </trkpt>
+ <trkpt lat="50.93577337239704" lon="-1.3960478015343325">
+ </trkpt>
+ <trkpt lat="50.935773925085456" lon="-1.3962967813167344">
+ </trkpt>
+ <trkpt lat="50.9357988806804" lon="-1.3963513403903836">
+ </trkpt>
+ <trkpt lat="50.93611836752382" lon="-1.3964473371226434">
+ </trkpt>
+ <trkpt lat="50.936481916060714" lon="-1.3970052501658414">
+ </trkpt>
+ <trkpt lat="50.93702687538352" lon="-1.3971227470089196">
+ </trkpt>
+ <trkpt lat="50.93706994387714" lon="-1.3965433381584087">
+ </trkpt>
+ <trkpt lat="50.93707557096683" lon="-1.3962678568788387">
+ </trkpt>
+ <trkpt lat="50.93784776846591" lon="-1.39639081319759">
+ </trkpt>
+ <trkpt lat="50.937936219176905" lon="-1.39639081319759">
+ </trkpt>
+ <trkpt lat="50.93797916385147" lon="-1.3963342765733557">
+ </trkpt>
+ <trkpt lat="50.93801967329006" lon="-1.3962610889524538">
+ </trkpt>
+ <trkpt lat="50.93804703291441" lon="-1.396188163531328">
+ </trkpt>
+ <trkpt lat="50.93833589850417" lon="-1.3933309823676083">
+ </trkpt>
+ <trkpt lat="50.93849862225774" lon="-1.3912812558890477">
+ </trkpt>
+ <trkpt lat="50.93860633888459" lon="-1.3901134772541726">
+ </trkpt>
+ <trkpt lat="50.938640039331915" lon="-1.3891990555206615">
+ </trkpt>
+ <trkpt lat="50.9385360982837" lon="-1.3864132150970063">
+ </trkpt>
+ <trkpt lat="50.938455179952356" lon="-1.3844281591914078">
+ </trkpt>
+ <trkpt lat="50.93852428079029" lon="-1.3836099837934306">
+ </trkpt>
+ <trkpt lat="50.93870549175904" lon="-1.382785926562627">
+ </trkpt>
+ <trkpt lat="50.93905714620233" lon="-1.3816170286423035">
+ </trkpt>
+ <trkpt lat="50.9393311742523" lon="-1.3802353508858132">
+ </trkpt>
+ <trkpt lat="50.939418119869046" lon="-1.3800264385031242">
+ </trkpt>
+ <trkpt lat="50.939904319926725" lon="-1.3795044909403058">
+ </trkpt>
+ <trkpt lat="50.940085689606555" lon="-1.3792662891294136">
+ </trkpt>
+ <trkpt lat="50.94023537675054" lon="-1.3789549110311963">
+ </trkpt>
+ <trkpt lat="50.940406149497065" lon="-1.378327355815691">
+ </trkpt>
+ <trkpt lat="50.94054473935883" lon="-1.3778628834602435">
+ </trkpt>
+ <trkpt lat="50.94091692384521" lon="-1.3772706452129186">
+ </trkpt>
+ <trkpt lat="50.94217301568485" lon="-1.376088709084551">
+ </trkpt>
+ <trkpt lat="50.94221766842468" lon="-1.3757448723583987">
+ </trkpt>
+ <trkpt lat="50.942128092724" lon="-1.3748819270762458">
+ </trkpt>
+ <trkpt lat="50.94207806145242" lon="-1.374764654751149">
+ </trkpt>
+ <trkpt lat="50.940998688662134" lon="-1.37585626936965">
+ </trkpt>
+ <trkpt lat="50.940907156770436" lon="-1.375862288751725">
+ </trkpt>
+ <trkpt lat="50.940444702175874" lon="-1.3755634713688587">
+ </trkpt>
+ <trkpt lat="50.94035751252145" lon="-1.3755706385785547">
+ </trkpt>
+ <trkpt lat="50.940115432293624" lon="-1.3756963153930557">
+ </trkpt>
+ <trkpt lat="50.93965098813528" lon="-1.375828966707219">
+ </trkpt>
+ <trkpt lat="50.939069812963794" lon="-1.3758442474251211">
+ </trkpt>
+ <trkpt lat="50.9376487112897" lon="-1.3758795503625463">
+ </trkpt>
+ <trkpt lat="50.9375779318684" lon="-1.375989641401273">
+ </trkpt>
+ <trkpt lat="50.93742480225192" lon="-1.3767048474530779">
+ </trkpt>
+ <trkpt lat="50.93729210253366" lon="-1.3772620360744519">
+ </trkpt>
+ <trkpt lat="50.93718264882213" lon="-1.377667971660513">
+ </trkpt>
+ <trkpt lat="50.936970149330264" lon="-1.3780303500154312">
+ </trkpt>
+ <trkpt lat="50.936734923573624" lon="-1.3782184589819453">
+ </trkpt>
+ <trkpt lat="50.93668803718873" lon="-1.3804217047131835">
+ </trkpt>
+ <trkpt lat="50.93658740138708" lon="-1.380430948028289">
+ </trkpt>
+ <trkpt lat="50.93475562656554" lon="-1.3815428713538895">
+ </trkpt>
+ <trkpt lat="50.934164655417995" lon="-1.3821749546837536">
+ </trkpt>
+ <trkpt lat="50.93272475259721" lon="-1.3838939777523551">
+ </trkpt>
+ <trkpt lat="50.93210643371271" lon="-1.3844245731868652">
+ </trkpt>
+ <trkpt lat="50.93145244689087" lon="-1.384896410373191">
+ </trkpt>
+ <trkpt lat="50.93120692899477" lon="-1.3850399278650019">
+ </trkpt>
+ <trkpt lat="50.93096297130888" lon="-1.3850935232724524">
+ </trkpt>
+ <trkpt lat="50.93042406817167" lon="-1.385287458346071">
+ </trkpt>
+ <trkpt lat="50.93012099469742" lon="-1.38529599481171">
+ </trkpt>
+ <trkpt lat="50.92982323409011" lon="-1.385210639162807">
+ </trkpt>
+ <trkpt lat="50.92922301314625" lon="-1.3852159978028036">
+ </trkpt>
+ <trkpt lat="50.92879857272864" lon="-1.3853654703398866">
+ </trkpt>
+ <trkpt lat="50.928406027786735" lon="-1.385692401424587">
+ </trkpt>
+ <trkpt lat="50.92782018147411" lon="-1.3868879769145022">
+ </trkpt>
+ <trkpt lat="50.92764658136017" lon="-1.3878382027377028">
+ </trkpt>
+ <trkpt lat="50.927533666584594" lon="-1.3886407452396468">
+ </trkpt>
+ <trkpt lat="50.92735812020966" lon="-1.3894313856308247">
+ </trkpt>
+ <trkpt lat="50.926926663533" lon="-1.3909028423298726">
+ </trkpt>
+ <trkpt lat="50.9264964339668" lon="-1.3916178947916782">
+ </trkpt>
+ <trkpt lat="50.92597736655241" lon="-1.3924099666533116">
+ </trkpt>
+ <trkpt lat="50.925430310022904" lon="-1.3930312188339522">
+ </trkpt>
+ <trkpt lat="50.92462090264638" lon="-1.3938716142530632">
+ </trkpt>
+ <trkpt lat="50.92390554355865" lon="-1.3946328267560977">
+ </trkpt>
+ <trkpt lat="50.922987755233024" lon="-1.395302822591703">
+ </trkpt>
+ <trkpt lat="50.922536573326084" lon="-1.3954269154296934">
+ </trkpt>
+ <trkpt lat="50.92000168056519" lon="-1.3953810363746364">
+ </trkpt>
+ <trkpt lat="50.919119458917834" lon="-1.3953306294139063">
+ </trkpt>
+ <trkpt lat="50.91819742134231" lon="-1.395454147765473">
+ </trkpt>
+ <trkpt lat="50.917220768617845" lon="-1.395633356999133">
+ </trkpt>
+ <trkpt lat="50.9163869182044" lon="-1.396155956581191">
+ </trkpt>
+ <trkpt lat="50.91575508381349" lon="-1.3966640661637708">
+ </trkpt>
+ <trkpt lat="50.9154223680708" lon="-1.397118936990208">
+ </trkpt>
+ <trkpt lat="50.91495693491732" lon="-1.3976125546750682">
+ </trkpt>
+ <trkpt lat="50.91376763637645" lon="-1.3987987330969536">
+ </trkpt>
+ <trkpt lat="50.912516678230496" lon="-1.4000590565577404">
+ </trkpt>
+ <trkpt lat="50.911839997121675" lon="-1.3998530854223954">
+ </trkpt>
+ <trkpt lat="50.911125525144065" lon="-1.3997288629031808">
+ </trkpt>
+ <trkpt lat="50.91103994792294" lon="-1.400066435302374">
+ </trkpt>
+ <trkpt lat="50.910947315753624" lon="-1.4003299819009352">
+ </trkpt>
+ <trkpt lat="50.910277056343" lon="-1.4003415443581355">
+ </trkpt>
+ <trkpt lat="50.91016089223864" lon="-1.400574693014231">
+ </trkpt>
+ <trkpt lat="50.91012129039976" lon="-1.401284775406461">
+ </trkpt>
+ <trkpt lat="50.91004933459241" lon="-1.4015113722252">
+ </trkpt>
+ <trkpt lat="50.90980214895626" lon="-1.4016678478426237">
+ </trkpt>
+ <trkpt lat="50.907124626313696" lon="-1.4014818549362948">
+ </trkpt>
+ <trkpt lat="50.90688725925504" lon="-1.4038140943783102">
+ </trkpt>
+ <trkpt lat="50.90688272508155" lon="-1.4045282807516808">
+ </trkpt>
+ <trkpt lat="50.90680762206483" lon="-1.4054493277537956">
+ </trkpt>
+ <trkpt lat="50.90679510488357" lon="-1.4057709001984993">
+ </trkpt>
+ <trkpt lat="50.906827649547765" lon="-1.4061123227941108">
+ </trkpt>
+ <trkpt lat="50.906815132371925" lon="-1.406378314816273">
+ </trkpt>
+ <trkpt lat="50.90678008426166" lon="-1.4065569661744415">
+ </trkpt>
+ <trkpt lat="50.90670550126423" lon="-1.4067016808382207">
+ </trkpt>
+ <trkpt lat="50.90608505367494" lon="-1.4066302319847759">
+ </trkpt>
+ <trkpt lat="50.9052785177942" lon="-1.4064078986047872">
+ </trkpt>
+ <trkpt lat="50.90422994191003" lon="-1.4061736785139003">
+ </trkpt>
+ <trkpt lat="50.90316841420774" lon="-1.4058699712050138">
+ </trkpt>
+ <trkpt lat="50.90272611108267" lon="-1.4056615329306599">
+ </trkpt>
+ <trkpt lat="50.90237475622175" lon="-1.4055424437150381">
+ </trkpt>
+ <trkpt lat="50.901618230388024" lon="-1.4050402232072505">
+ </trkpt>
+ <trkpt lat="50.90114793965596" lon="-1.4048516584634523">
+ </trkpt>
+ <trkpt lat="50.90040682664022" lon="-1.4048179132069099">
+ </trkpt>
+ <trkpt lat="50.90027412610509" lon="-1.404784167950366">
+ </trkpt>
+ <trkpt lat="50.90018858719017" lon="-1.4046531452645517">
+ </trkpt>
+ <trkpt lat="50.90020652380025" lon="-1.404006042034787">
+ </trkpt>
+ <trkpt lat="50.90016354926495" lon="-1.4039345698016954">
+ </trkpt>
+ <trkpt lat="50.89949418984475" lon="-1.4038889261444318">
+ </trkpt>
+ <trkpt lat="50.898876991859375" lon="-1.4039048062651573">
+ </trkpt>
+ <trkpt lat="50.898319469060866" lon="-1.4040179404355073">
+ </trkpt>
+ <trkpt lat="50.89686634696341" lon="-1.4043295994945808">
+ </trkpt>
+ <trkpt lat="50.89652956171463" lon="-1.4046114716374694">
+ </trkpt>
+ <trkpt lat="50.8964031101187" lon="-1.4045797113960172">
+ </trkpt>
+ <trkpt lat="50.89630379209065" lon="-1.404407003393297">
+ </trkpt>
+ <trkpt lat="50.896083849611" lon="-1.4032616613757498">
+ </trkpt>
+ <trkpt lat="50.896062565499356" lon="-1.402771362648331">
+ </trkpt>
+ <trkpt lat="50.89614603977688" lon="-1.4024696286647114">
+ </trkpt>
+ <trkpt lat="50.89628166618351" lon="-1.402106382592925">
+ </trkpt>
+ <trkpt lat="50.89655419149132" lon="-1.4016061471002288">
+ </trkpt>
+ <trkpt lat="50.897003655038105" lon="-1.4014731510891476">
+ </trkpt>
+ <trkpt lat="50.897779877132024" lon="-1.4004746884984935">
+ </trkpt>
+ <trkpt lat="50.897626295806305" lon="-1.3990752645493296">
+ </trkpt>
+ <trkpt lat="50.89744560242939" lon="-1.3978465285183221">
+ </trkpt>
+ <trkpt lat="50.89736588639692" lon="-1.397483282446537">
+ </trkpt>
+ <trkpt lat="50.897302035790595" lon="-1.3974356420843594">
+ </trkpt>
+ <trkpt lat="50.897161404446685" lon="-1.397495180847257">
+ </trkpt>
+ <trkpt lat="50.897039962489" lon="-1.3977988881561436">
+ </trkpt>
+ <trkpt lat="50.896970261622805" lon="-1.3985750407464568">
+ </trkpt>
+ <trkpt lat="50.89687886681419" lon="-1.3987417820140817">
+ </trkpt>
+ <trkpt lat="50.896748250100785" lon="-1.3987973507467977">
+ </trkpt>
+ <trkpt lat="50.896038367255905" lon="-1.3985492238604527">
+ </trkpt>
+ <trkpt lat="50.89577920098118" lon="-1.398047015042489">
+ </trkpt>
+ <trkpt lat="50.89528089655506" lon="-1.3981681009630265">
+ </trkpt>
+ <trkpt lat="50.89400797692971" lon="-1.397677813925432">
+ </trkpt>
+ <trkpt lat="50.893967500800166" lon="-1.3975884765565227">
+ </trkpt>
+ <trkpt lat="50.89401799342536" lon="-1.3972033953187402">
+ </trkpt>
+ <trkpt lat="50.8940038106182" lon="-1.3970326723311093">
+ </trkpt>
+ <trkpt lat="50.89385772923645" lon="-1.3965463553236968">
+ </trkpt>
+ <trkpt lat="50.893710827141184" lon="-1.395460540379224">
+ </trkpt>
+ <trkpt lat="50.89366240651057" lon="-1.3950734741263497">
+ </trkpt>
+ <trkpt lat="50.893644467379715" lon="-1.3950476572403456">
+ </trkpt>
+ <trkpt lat="50.89355973654419" lon="-1.3950615640358048">
+ </trkpt>
+ <trkpt lat="50.89346633217334" lon="-1.39492943698846">
+ </trkpt>
+ <trkpt lat="50.89329512907658" lon="-1.3946793935459965">
+ </trkpt>
+ <trkpt lat="50.893189945189164" lon="-1.3947414590670397">
+ </trkpt>
+ <trkpt lat="50.89316407943496" lon="-1.3949762083869022">
+ </trkpt>
+ <trkpt lat="50.8933506396932" lon="-1.395375196420146">
+ </trkpt>
+ <trkpt lat="50.893428168572434" lon="-1.395439025736803">
+ </trkpt>
+ <trkpt lat="50.89352194213996" lon="-1.3954131963367211">
+ </trkpt>
+ <trkpt lat="50.89356098861828" lon="-1.3952699906203354">
+ </trkpt>
+ <trkpt lat="50.89354648027707" lon="-1.3951114598646075">
+ </trkpt>
+ <trkpt lat="50.89355973654419" lon="-1.3950615640358053">
+ </trkpt>
+ <trkpt lat="50.893646661396055" lon="-1.3950415026910055">
+ </trkpt>
+ <trkpt lat="50.89366240651059" lon="-1.3950695040961685">
+ </trkpt>
+ <trkpt lat="50.89371499347891" lon="-1.3954605520690488">
+ </trkpt>
+ <trkpt lat="50.89385730646264" lon="-1.396545247577808">
+ </trkpt>
+ <trkpt lat="50.894002533261165" lon="-1.3970254442094887">
+ </trkpt>
+ <trkpt lat="50.894017993425386" lon="-1.3972014103036492">
+ </trkpt>
+ <trkpt lat="50.893969089817745" lon="-1.3975865849168028">
+ </trkpt>
+ <trkpt lat="50.89400922899177" lon="-1.397677813925432">
+ </trkpt>
+ <trkpt lat="50.895310746116095" lon="-1.3981802738562559">
+ </trkpt>
+ <trkpt lat="50.89548869893021" lon="-1.398225894973857">
+ </trkpt>
+ <trkpt lat="50.89563836431316" lon="-1.398510481689133">
+ </trkpt>
+ <trkpt lat="50.89591806950092" lon="-1.3984935798441676">
+ </trkpt>
+ <trkpt lat="50.896749294504026" lon="-1.3987960458735784">
+ </trkpt>
+ <trkpt lat="50.89685507909488" lon="-1.39894623856843">
+ </trkpt>
+ <trkpt lat="50.89683788181229" lon="-1.3996268806701961">
+ </trkpt>
+ <trkpt lat="50.896747408213216" lon="-1.4003972845997779">
+ </trkpt>
+ <trkpt lat="50.89668289327428" lon="-1.400693231061953">
+ </trkpt>
+ <trkpt lat="50.89649707714679" lon="-1.4014092555068844">
+ </trkpt>
+ <trkpt lat="50.89626038216225" lon="-1.4021818131663741">
+ </trkpt>
+ <trkpt lat="50.89614930708994" lon="-1.4024737035208414">
+ </trkpt>
+ <trkpt lat="50.89606131349246" lon="-1.4027634225879682">
+ </trkpt>
+ <trkpt lat="50.896082597604725" lon="-1.4032616613757496">
+ </trkpt>
+ <trkpt lat="50.89630421736951" lon="-1.4044068184849172">
+ </trkpt>
+ <trkpt lat="50.89640436211637" lon="-1.404573756350745">
+ </trkpt>
+ <trkpt lat="50.89653081370892" lon="-1.4046174266827416">
+ </trkpt>
+ <trkpt lat="50.89686992008634" lon="-1.404323385264984">
+ </trkpt>
+ <trkpt lat="50.89831955893268" lon="-1.4040218866791574">
+ </trkpt>
+ <trkpt lat="50.89887573992815" lon="-1.4039048062651571">
+ </trkpt>
+ <trkpt lat="50.8994979455884" lon="-1.4038909111595226">
+ </trkpt>
+ <trkpt lat="50.90016489102978" lon="-1.4039405010604356">
+ </trkpt>
+ <trkpt lat="50.90020652380026" lon="-1.4040040570196963">
+ </trkpt>
+ <trkpt lat="50.9001899289543" lon="-1.4046551064931105">
+ </trkpt>
+ <trkpt lat="50.900276629892275" lon="-1.4047821829352758">
+ </trkpt>
+ <trkpt lat="50.900400567189514" lon="-1.4048119581616374">
+ </trkpt>
+ <trkpt lat="50.90114418404542" lon="-1.4048536434785428">
+ </trkpt>
+ <trkpt lat="50.90161832025348" lon="-1.4050421844358092">
+ </trkpt>
+ <trkpt lat="50.90237225254738" lon="-1.4055444287301282">
+ </trkpt>
+ <trkpt lat="50.90272244546274" lon="-1.405661509144128">
+ </trkpt>
+ <trkpt lat="50.90316716239192" lon="-1.4058679861899228">
+ </trkpt>
+ <trkpt lat="50.90423369727167" lon="-1.4061716934988093">
+ </trkpt>
+ <trkpt lat="50.90527610413441" lon="-1.4064039047880734">
+ </trkpt>
+ <trkpt lat="50.90608255020011" lon="-1.406630231984776">
+ </trkpt>
+ <trkpt lat="50.9067030876784" lon="-1.4066996720365976">
+ </trkpt>
+ <trkpt lat="50.906888341983205" lon="-1.4065924812216966">
+ </trkpt>
+ <trkpt lat="50.906924890730366" lon="-1.4063829901998495">
+ </trkpt>
+ <trkpt lat="50.906906731379266" lon="-1.4057005564749612">
+ </trkpt>
+ <trkpt lat="50.906881230683794" lon="-1.4045291799144164">
+ </trkpt>
+ <trkpt lat="50.906889422107504" lon="-1.4038268777075698">
+ </trkpt>
+ <trkpt lat="50.9071240413654" lon="-1.4014866918590898">
+ </trkpt>
+ <trkpt lat="50.90980651848476" lon="-1.4016648273423462">
+ </trkpt>
+ <trkpt lat="50.9100534525073" lon="-1.4015047464733892">
+ </trkpt>
+ <trkpt lat="50.91012306047019" lon="-1.4012931971122498">
+ </trkpt>
+ <trkpt lat="50.91016061102434" lon="-1.4005688652786905">
+ </trkpt>
+ <trkpt lat="50.9102752862784" lon="-1.4003387371228724">
+ </trkpt>
+ <trkpt lat="50.91095259624665" lon="-1.400331296209488">
+ </trkpt>
+ <trkpt lat="50.9110417179585" lon="-1.4000692425376366">
+ </trkpt>
+ <trkpt lat="50.911122363354835" lon="-1.3997287322754564">
+ </trkpt>
+ <trkpt lat="50.9118329171006" lon="-1.3998530854223956">
+ </trkpt>
+ <trkpt lat="50.91251285707147" lon="-1.4000612515198534">
+ </trkpt>
+ <trkpt lat="50.91376749280461" lon="-1.3987975649635553">
+ </trkpt>
+ <trkpt lat="50.914954024952294" lon="-1.3976092178039463">
+ </trkpt>
+ <trkpt lat="50.91542623394892" lon="-1.3971131918919582">
+ </trkpt>
+ <trkpt lat="50.91575862352585" lon="-1.3966612589285086">
+ </trkpt>
+ <trkpt lat="50.91638868803658" lon="-1.3961531493459283">
+ </trkpt>
+ <trkpt lat="50.91722441854935" lon="-1.395629335538283">
+ </trkpt>
+ <trkpt lat="50.91819742134231" lon="-1.3954541477654727">
+ </trkpt>
+ <trkpt lat="50.91911768918949" lon="-1.3953306294139065">
+ </trkpt>
+ <trkpt lat="50.919994156941385" lon="-1.3953900877992496">
+ </trkpt>
+ <trkpt lat="50.92253966770262" lon="-1.3954281094312344">
+ </trkpt>
+ <trkpt lat="50.922984216070546" lon="-1.395305629826966">
+ </trkpt>
+ <trkpt lat="50.923915056725455" lon="-1.3946414791725756">
+ </trkpt>
+ <trkpt lat="50.924625907601786" lon="-1.3938807171083452">
+ </trkpt>
+ <trkpt lat="50.92542912781598" lon="-1.3930273213290385">
+ </trkpt>
+ <trkpt lat="50.925977366552395" lon="-1.3924085630356804">
+ </trkpt>
+ <trkpt lat="50.926496433966825" lon="-1.3916178947916782">
+ </trkpt>
+ <trkpt lat="50.92693258513273" lon="-1.3909045179768396">
+ </trkpt>
+ <trkpt lat="50.927352900882155" lon="-1.3894231049957153">
+ </trkpt>
+ <trkpt lat="50.92753366658462" lon="-1.3886387602245562">
+ </trkpt>
+ <trkpt lat="50.92764467076673" lon="-1.3878380586441599">
+ </trkpt>
+ <trkpt lat="50.92782393493256" lon="-1.3868879769145026">
+ </trkpt>
+ <trkpt lat="50.92840411722448" lon="-1.3856922573310437">
+ </trkpt>
+ <trkpt lat="50.92880107498167" lon="-1.3853654703398863">
+ </trkpt>
+ <trkpt lat="50.92922610707806" lon="-1.3852198237394422">
+ </trkpt>
+ <trkpt lat="50.92982073189206" lon="-1.3852126241778975">
+ </trkpt>
+ <trkpt lat="50.93011849251539" lon="-1.38529599481171">
+ </trkpt>
+ <trkpt lat="50.93042090660942" lon="-1.385285329237437">
+ </trkpt>
+ <trkpt lat="50.9309654734455" lon="-1.3850955082875431">
+ </trkpt>
+ <trkpt lat="50.93120818005655" lon="-1.3850399278650019">
+ </trkpt>
+ <trkpt lat="50.93145303856414" lon="-1.3848962662796476">
+ </trkpt>
+ <trkpt lat="50.932101429562124" lon="-1.3844186181415932">
+ </trkpt>
+ <trkpt lat="50.93272409323336" lon="-1.383893833658812">
+ </trkpt>
+ <trkpt lat="50.93416274509228" lon="-1.3821926757260272">
+ </trkpt>
+ <trkpt lat="50.93476063043057" lon="-1.3815349312935272">
+ </trkpt>
+ <trkpt lat="50.93658300322116" lon="-1.380440629869021">
+ </trkpt>
+ <trkpt lat="50.93922976326573" lon="-1.380021076509329">
+ </trkpt>
+ <trkpt lat="50.93941907550448" lon="-1.3800230542318228">
+ </trkpt>
+ <trkpt lat="50.93990431992674" lon="-1.3795084609704875">
+ </trkpt>
+ <trkpt lat="50.940085689606526" lon="-1.3792682741445046">
+ </trkpt>
+ <trkpt lat="50.9402358674192" lon="-1.3789531310979013">
+ </trkpt>
+ <trkpt lat="50.94040347684946" lon="-1.3783278513443105">
+ </trkpt>
+ <trkpt lat="50.94054348854823" lon="-1.377860898445153">
+ </trkpt>
+ <trkpt lat="50.940916307920936" lon="-1.377271823316024">
+ </trkpt>
+ <trkpt lat="50.942174516992004" lon="-1.376092249999283">
+ </trkpt>
+ <trkpt lat="50.94221649695807" lon="-1.3757463392187723">
+ </trkpt>
+ <trkpt lat="50.942128718108" lon="-1.3748789495536096">
+ </trkpt>
+ <trkpt lat="50.94207703638274" lon="-1.374763756748844">
+ </trkpt>
+ <trkpt lat="50.94099681246453" lon="-1.3758582543847415">
+ </trkpt>
+ <trkpt lat="50.94090817771636" lon="-1.375863455109127">
+ </trkpt>
+ <trkpt lat="50.94044423244344" lon="-1.3755624532071031">
+ </trkpt>
+ <trkpt lat="50.94035751252145" lon="-1.3755696460710094">
+ </trkpt>
+ <trkpt lat="50.94011586150794" lon="-1.3756949823107638">
+ </trkpt>
+ <trkpt lat="50.93965195200975" lon="-1.375830040961434">
+ </trkpt>
+ <trkpt lat="50.93906944659823" lon="-1.375845651042753">
+ </trkpt>
+ <trkpt lat="50.93764726733585" lon="-1.3758786216268686">
+ </trkpt>
+ <trkpt lat="50.93757753945346" lon="-1.3759908041961906">
+ </trkpt>
+ <trkpt lat="50.93742456695998" lon="-1.376702123984975">
+ </trkpt>
+ <trkpt lat="50.93729210253371" lon="-1.377265013597088">
+ </trkpt>
+ <trkpt lat="50.93718264882213" lon="-1.3776709491831494">
+ </trkpt>
+ <trkpt lat="50.936967362763426" lon="-1.378032084095787">
+ </trkpt>
+ <trkpt lat="50.93673512907553" lon="-1.3782197556719467">
+ </trkpt>
+ <trkpt lat="50.9366888021275" lon="-1.3805291646209947">
+ </trkpt>
+ <trkpt lat="50.93687409631645" lon="-1.3811758330405808">
+ </trkpt>
+ <trkpt lat="50.93766611276506" lon="-1.3827922076885986">
+ </trkpt>
+ <trkpt lat="50.938458602051874" lon="-1.3844285665050116">
+ </trkpt>
+ <trkpt lat="50.93846249497054" lon="-1.3845941472575223">
+ </trkpt>
+ <trkpt lat="50.93853407875549" lon="-1.3864090766471353">
+ </trkpt>
+ <trkpt lat="50.938640288621464" lon="-1.3892040559315526">
+ </trkpt>
+ <trkpt lat="50.938607223378106" lon="-1.3901092664012789">
+ </trkpt>
+ <trkpt lat="50.938499677844966" lon="-1.3912837538426246">
+ </trkpt>
+ <trkpt lat="50.93833555825733" lon="-1.3933310000852606">
+ </trkpt>
+ <trkpt lat="50.938050635455156" lon="-1.3961830620857318">
+ </trkpt>
+ <trkpt lat="50.93802055779473" lon="-1.3962624925700848">
+ </trkpt>
+ <trkpt lat="50.93798154359171" lon="-1.3963360721099638">
+ </trkpt>
+ <trkpt lat="50.9379364782428" lon="-1.3963885873597865">
+ </trkpt>
+ <trkpt lat="50.93784688395793" lon="-1.3963894095799583">
+ </trkpt>
+ <trkpt lat="50.93707428914198" lon="-1.3962571727266795">
+ </trkpt>
+ <trkpt lat="50.935771078981425" lon="-1.396046434511756">
+ </trkpt>
+ <trkpt lat="50.935775319294216" lon="-1.396297008660216">
+ </trkpt>
+ <trkpt lat="50.93580123782743" lon="-1.3963542000803142">
+ </trkpt>
+ <trkpt lat="50.9361190049163" lon="-1.3964480882716002">
+ </trkpt>
+ <trkpt lat="50.936482796822226" lon="-1.3970034547715509">
+ </trkpt>
+ <trkpt lat="50.93702649769812" lon="-1.3971243352010767">
+ </trkpt>
+ <trkpt lat="50.93707060759229" lon="-1.3965419716441054">
+ </trkpt>
+ </trkseg>
+ </trk>
+</gpx> \ No newline at end of file
diff --git a/res/raw/u9.gpx b/res/raw/u9.gpx
new file mode 100644
index 0000000..2226b49
--- /dev/null
+++ b/res/raw/u9.gpx
@@ -0,0 +1,378 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
+ <metadata>
+ <author>
+ <name>chrisb8</name>
+ </author>
+ <copyright author="chrisb8">
+ <year>2012</year>
+ <license>http://creativecommons.org/licenses/by-sa/2.5</license>
+ </copyright>
+ <bounds minlat="50.9210678" minlon="-1.4331712" maxlat="50.937902" maxlon="-1.354205" />
+ </metadata>
+ <trk> <trkseg>
+ <trkpt lat="50.9233868815378" lon="-1.42097958571668">
+ </trkpt>
+ <trkpt lat="50.92792127066787" lon="-1.425457779761443">
+ </trkpt>
+ <trkpt lat="50.92957998418787" lon="-1.427081171505357">
+ </trkpt>
+ <trkpt lat="50.92895943170261" lon="-1.4287803444230511">
+ </trkpt>
+ <trkpt lat="50.93073098703966" lon="-1.430487457401108">
+ </trkpt>
+ <trkpt lat="50.931506646809446" lon="-1.4310512016868848">
+ </trkpt>
+ <trkpt lat="50.93185694052997" lon="-1.4320675294133558">
+ </trkpt>
+ <trkpt lat="50.932492466687584" lon="-1.4315355453690308">
+ </trkpt>
+ <trkpt lat="50.93376849692243" lon="-1.4314323245843112">
+ </trkpt>
+ <trkpt lat="50.93460915653464" lon="-1.4331711978038206">
+ </trkpt>
+ <trkpt lat="50.93375348500554" lon="-1.4315990658519353">
+ </trkpt>
+ <trkpt lat="50.93252249133059" lon="-1.4317261068177443">
+ </trkpt>
+ <trkpt lat="50.93185193635254" lon="-1.4322104504998907">
+ </trkpt>
+ <trkpt lat="50.93152165945159" lon="-1.4309241607210754">
+ </trkpt>
+ <trkpt lat="50.93073098703967" lon="-1.4303524763749356">
+ </trkpt>
+ <trkpt lat="50.929094552706886" lon="-1.4287565242419613">
+ </trkpt>
+ <trkpt lat="50.92968007252306" lon="-1.4270891115657198">
+ </trkpt>
+ <trkpt lat="50.92788845874722" lon="-1.4252787778029437">
+ </trkpt>
+ <trkpt lat="50.92519590380054" lon="-1.4226347377020458">
+ </trkpt>
+ <trkpt lat="50.92338439163298" lon="-1.420816741867532">
+ </trkpt>
+ <trkpt lat="50.92243918222688" lon="-1.4195188358852335">
+ </trkpt>
+ <trkpt lat="50.92164993302721" lon="-1.4176267593180565">
+ </trkpt>
+ <trkpt lat="50.92141280172836" lon="-1.415263067226717">
+ </trkpt>
+ <trkpt lat="50.924220330713574" lon="-1.4152475861141258">
+ </trkpt>
+ <trkpt lat="50.93404374774146" lon="-1.418616268429574">
+ </trkpt>
+ <trkpt lat="50.934298506172354" lon="-1.4143941865942125">
+ </trkpt>
+ <trkpt lat="50.935218455553965" lon="-1.4106661781651164">
+ </trkpt>
+ <trkpt lat="50.93582625778413" lon="-1.4064409391021908">
+ </trkpt>
+ <trkpt lat="50.93646299660221" lon="-1.4040896028618808">
+ </trkpt>
+ <trkpt lat="50.9365962931998" lon="-1.403727452990551">
+ </trkpt>
+ <trkpt lat="50.93701839657151" lon="-1.4020769469397987">
+ </trkpt>
+ <trkpt lat="50.937769984674965" lon="-1.399351271388433">
+ </trkpt>
+ <trkpt lat="50.93789963739411" lon="-1.3971463466664562">
+ </trkpt>
+ <trkpt lat="50.93784213332737" lon="-1.3967452427063902">
+ </trkpt>
+ <trkpt lat="50.937799806597816" lon="-1.396610496624893">
+ </trkpt>
+ <trkpt lat="50.937228330832895" lon="-1.3965123148485246">
+ </trkpt>
+ <trkpt lat="50.935828150657194" lon="-1.3962591313880202">
+ </trkpt>
+ <trkpt lat="50.93560561038891" lon="-1.3962352791719905">
+ </trkpt>
+ <trkpt lat="50.93562775918166" lon="-1.3964129015985811">
+ </trkpt>
+ <trkpt lat="50.93571236607881" lon="-1.3965924002085366">
+ </trkpt>
+ <trkpt lat="50.936032724571575" lon="-1.3966946773898428">
+ </trkpt>
+ <trkpt lat="50.93637687556976" lon="-1.3972320283983397">
+ </trkpt>
+ <trkpt lat="50.93716058118719" lon="-1.3973822445092852">
+ </trkpt>
+ <trkpt lat="50.937229789866635" lon="-1.3965132319321887">
+ </trkpt>
+ <trkpt lat="50.93582940159464" lon="-1.396261116403111">
+ </trkpt>
+ <trkpt lat="50.9356075480705" lon="-1.396236777721176">
+ </trkpt>
+ <trkpt lat="50.935601364031264" lon="-1.3961763421516677">
+ </trkpt>
+ <trkpt lat="50.935199460416655" lon="-1.3963511752334388">
+ </trkpt>
+ <trkpt lat="50.93477457682465" lon="-1.3964659075565984">
+ </trkpt>
+ <trkpt lat="50.93444575429481" lon="-1.396429583329524">
+ </trkpt>
+ <trkpt lat="50.93380942358292" lon="-1.396037845497655">
+ </trkpt>
+ <trkpt lat="50.93341556525665" lon="-1.3957199404345744">
+ </trkpt>
+ <trkpt lat="50.93230698455466" lon="-1.3953227350757127">
+ </trkpt>
+ <trkpt lat="50.93220724595246" lon="-1.3952300821337198">
+ </trkpt>
+ <trkpt lat="50.93148241399062" lon="-1.3930452459174085">
+ </trkpt>
+ <trkpt lat="50.93099746903262" lon="-1.3908009944462028">
+ </trkpt>
+ <trkpt lat="50.93026828887891" lon="-1.390687284303313">
+ </trkpt>
+ <trkpt lat="50.92974310282417" lon="-1.3907018222851228">
+ </trkpt>
+ <trkpt lat="50.92912255251511" lon="-1.3908387883263849">
+ </trkpt>
+ <trkpt lat="50.92727145024017" lon="-1.391549246599694">
+ </trkpt>
+ <trkpt lat="50.927028760460146" lon="-1.3911080874513853">
+ </trkpt>
+ <trkpt lat="50.9266163010373" lon="-1.391484422251192">
+ </trkpt>
+ <trkpt lat="50.92607838720991" lon="-1.3906759384954843">
+ </trkpt>
+ <trkpt lat="50.92596377970233" lon="-1.3903421062199641">
+ </trkpt>
+ <trkpt lat="50.92585952274473" lon="-1.3902135085727927">
+ </trkpt>
+ <trkpt lat="50.9255004530269" lon="-1.3894403276150493">
+ </trkpt>
+ <trkpt lat="50.92535633279417" lon="-1.3890447407816269">
+ </trkpt>
+ <trkpt lat="50.92499634762868" lon="-1.3874574432665998">
+ </trkpt>
+ <trkpt lat="50.92502632153828" lon="-1.38692808539342">
+ </trkpt>
+ <trkpt lat="50.92514144679331" lon="-1.3855934390520515">
+ </trkpt>
+ <trkpt lat="50.925195308827725" lon="-1.384599483742867">
+ </trkpt>
+ <trkpt lat="50.92516699686392" lon="-1.3841096211894952">
+ </trkpt>
+ <trkpt lat="50.92508570753358" lon="-1.383624163515146">
+ </trkpt>
+ <trkpt lat="50.924565471222586" lon="-1.3814078512751076">
+ </trkpt>
+ <trkpt lat="50.92449255268605" lon="-1.3810089873066989">
+ </trkpt>
+ <trkpt lat="50.92435135867" lon="-1.3765765993877022">
+ </trkpt>
+ <trkpt lat="50.92454713458831" lon="-1.3759691693753036">
+ </trkpt>
+ <trkpt lat="50.92506264298373" lon="-1.3757984580774978">
+ </trkpt>
+ <trkpt lat="50.92566871066242" lon="-1.3759105338056277">
+ </trkpt>
+ <trkpt lat="50.92729660303631" lon="-1.377628561786506">
+ </trkpt>
+ <trkpt lat="50.92739569029803" lon="-1.376258630978224">
+ </trkpt>
+ <trkpt lat="50.92934200443296" lon="-1.3753490867530531">
+ </trkpt>
+ <trkpt lat="50.930630065731904" lon="-1.3744283135868303">
+ </trkpt>
+ <trkpt lat="50.931366084745065" lon="-1.373170672189063">
+ </trkpt>
+ <trkpt lat="50.931981784011114" lon="-1.3716996809113176">
+ </trkpt>
+ <trkpt lat="50.93242763011575" lon="-1.3708575103324554">
+ </trkpt>
+ <trkpt lat="50.932795626855416" lon="-1.370486955277756">
+ </trkpt>
+ <trkpt lat="50.93309285286564" lon="-1.3716547651471112">
+ </trkpt>
+ <trkpt lat="50.933496227984136" lon="-1.3707564498629918">
+ </trkpt>
+ <trkpt lat="50.93354576503818" lon="-1.3693865190547096">
+ </trkpt>
+ <trkpt lat="50.93443742298837" lon="-1.366051523562416">
+ </trkpt>
+ <trkpt lat="50.93444449957039" lon="-1.3652430398067084">
+ </trkpt>
+ <trkpt lat="50.934111899051395" lon="-1.3641762904068164">
+ </trkpt>
+ <trkpt lat="50.93318485100766" lon="-1.3628512753627402">
+ </trkpt>
+ <trkpt lat="50.932363938076755" lon="-1.3622561414870111">
+ </trkpt>
+ <trkpt lat="50.93135193064311" lon="-1.3609648132660892">
+ </trkpt>
+ <trkpt lat="50.93050975382413" lon="-1.3590446643462837">
+ </trkpt>
+ <trkpt lat="50.930007271315915" lon="-1.3580902043569067">
+ </trkpt>
+ <trkpt lat="50.92946231936127" lon="-1.357854396594825">
+ </trkpt>
+ <trkpt lat="50.928393628809395" lon="-1.3562486580244617">
+ </trkpt>
+ <trkpt lat="50.92775664925227" lon="-1.355732126736093">
+ </trkpt>
+ <trkpt lat="50.92673038606315" lon="-1.3551482218014153">
+ </trkpt>
+ <trkpt lat="50.926142928668995" lon="-1.3542049907530898">
+ </trkpt>
+ <trkpt lat="50.9253643592457" lon="-1.3548787272161793">
+ </trkpt>
+ <trkpt lat="50.92191018503667" lon="-1.3561363686139467">
+ </trkpt>
+ <trkpt lat="50.92106783726798" lon="-1.3567876471949334">
+ </trkpt>
+ <trkpt lat="50.92271712573955" lon="-1.360807608091368">
+ </trkpt>
+ <trkpt lat="50.923021494474845" lon="-1.361211849969222">
+ </trkpt>
+ <trkpt lat="50.92370808640276" lon="-1.3609086685608318">
+ </trkpt>
+ <trkpt lat="50.92444421494606" lon="-1.361211849969222">
+ </trkpt>
+ <trkpt lat="50.925222799768775" lon="-1.3632667461816452">
+ </trkpt>
+ <trkpt lat="50.92659590851922" lon="-1.3648163400467515">
+ </trkpt>
+ <trkpt lat="50.92723998164913" lon="-1.3646703638130822">
+ </trkpt>
+ <trkpt lat="50.928867819038175" lon="-1.3654563896866867">
+ </trkpt>
+ <trkpt lat="50.929646329826134" lon="-1.3660178367392615">
+ </trkpt>
+ <trkpt lat="50.932880548766455" lon="-1.3691057955284225">
+ </trkpt>
+ <trkpt lat="50.932887625585366" lon="-1.3704083526903956">
+ </trkpt>
+ <trkpt lat="50.93244153242094" lon="-1.370904270041073">
+ </trkpt>
+ <trkpt lat="50.93166129916629" lon="-1.3723556106719788">
+ </trkpt>
+ <trkpt lat="50.93057678759105" lon="-1.3742840160229914">
+ </trkpt>
+ <trkpt lat="50.92736364143391" lon="-1.3761367912964881">
+ </trkpt>
+ <trkpt lat="50.92642938107877" lon="-1.3750588129555448">
+ </trkpt>
+ <trkpt lat="50.92551633578488" lon="-1.37449736590297">
+ </trkpt>
+ <trkpt lat="50.92313808717219" lon="-1.374654571077691">
+ </trkpt>
+ <trkpt lat="50.924236990469716" lon="-1.3760971751658555">
+ </trkpt>
+ <trkpt lat="50.92431750418113" lon="-1.3763091214282022">
+ </trkpt>
+ <trkpt lat="50.92435023056274" lon="-1.3765789308503908">
+ </trkpt>
+ <trkpt lat="50.9244875477163" lon="-1.3810089873066989">
+ </trkpt>
+ <trkpt lat="50.92456434312049" lon="-1.381410182737796">
+ </trkpt>
+ <trkpt lat="50.92508280994269" lon="-1.383625091360203">
+ </trkpt>
+ <trkpt lat="50.925169651111254" lon="-1.3841124284247581">
+ </trkpt>
+ <trkpt lat="50.92519265458186" lon="-1.3846008873604982">
+ </trkpt>
+ <trkpt lat="50.92514031870517" lon="-1.385594366897109">
+ </trkpt>
+ <trkpt lat="50.92502720629006" lon="-1.386923874540526">
+ </trkpt>
+ <trkpt lat="50.92499875854656" lon="-1.3874569674940256">
+ </trkpt>
+ <trkpt lat="50.925355448048634" lon="-1.3890419335463644">
+ </trkpt>
+ <trkpt lat="50.925498168972744" lon="-1.3894385137473915">
+ </trkpt>
+ <trkpt lat="50.92586014834755" lon="-1.390210531050157">
+ </trkpt>
+ <trkpt lat="50.925965212447416" lon="-1.3903413432932397">
+ </trkpt>
+ <trkpt lat="50.92659272345075" lon="-1.3904804931025005">
+ </trkpt>
+ <trkpt lat="50.92667834254263" lon="-1.3905464809970813">
+ </trkpt>
+ <trkpt lat="50.92684880940291" lon="-1.390782366383661">
+ </trkpt>
+ <trkpt lat="50.927270515295085" lon="-1.3915492040647415">
+ </trkpt>
+ <trkpt lat="50.92912255251511" lon="-1.3908387883263853">
+ </trkpt>
+ <trkpt lat="50.929741723500975" lon="-1.3907038222296886">
+ </trkpt>
+ <trkpt lat="50.930269187881976" lon="-1.3906869346719424">
+ </trkpt>
+ <trkpt lat="50.93099766265055" lon="-1.3908002707617568">
+ </trkpt>
+ <trkpt lat="50.93148260760655" lon="-1.3930461950299422">
+ </trkpt>
+ <trkpt lat="50.93220583023568" lon="-1.3952276566920645">
+ </trkpt>
+ <trkpt lat="50.93230435783926" lon="-1.3953224588072053">
+ </trkpt>
+ <trkpt lat="50.933417441760156" lon="-1.3957199404345741">
+ </trkpt>
+ <trkpt lat="50.93380962933239" lon="-1.3960385353566422">
+ </trkpt>
+ <trkpt lat="50.93444387783281" lon="-1.396429583329523">
+ </trkpt>
+ <trkpt lat="50.934774218593994" lon="-1.3964657089125894">
+ </trkpt>
+ <trkpt lat="50.93519820946225" lon="-1.3963491902183482">
+ </trkpt>
+ <trkpt lat="50.935600941076714" lon="-1.3961758003069777">
+ </trkpt>
+ <trkpt lat="50.93562918348669" lon="-1.3964118282201525">
+ </trkpt>
+ <trkpt lat="50.935714988754974" lon="-1.39659002852687">
+ </trkpt>
+ <trkpt lat="50.93603705758698" lon="-1.3966981552895363">
+ </trkpt>
+ <trkpt lat="50.93637873573992" lon="-1.3972315375143571">
+ </trkpt>
+ <trkpt lat="50.93716212853907" lon="-1.3973831638253187">
+ </trkpt>
+ <trkpt lat="50.93722939064484" lon="-1.3965128398990097">
+ </trkpt>
+ <trkpt lat="50.937799054003506" lon="-1.396611362930819">
+ </trkpt>
+ <trkpt lat="50.93783985352797" lon="-1.3967501102786013">
+ </trkpt>
+ <trkpt lat="50.937902020251386" lon="-1.3971465042081832">
+ </trkpt>
+ <trkpt lat="50.937765778723914" lon="-1.399352098605119">
+ </trkpt>
+ <trkpt lat="50.93702322907852" lon="-1.4020720019090567">
+ </trkpt>
+ <trkpt lat="50.9365983128423" lon="-1.4037242481244332">
+ </trkpt>
+ <trkpt lat="50.93646010871978" lon="-1.4040872910278914">
+ </trkpt>
+ <trkpt lat="50.935827824082466" lon="-1.4064420949571654">
+ </trkpt>
+ <trkpt lat="50.935046273797084" lon="-1.4105762837554563">
+ </trkpt>
+ <trkpt lat="50.934119244378984" lon="-1.414337979007707">
+ </trkpt>
+ <trkpt lat="50.93387156163531" lon="-1.4183916267272962">
+ </trkpt>
+ <trkpt lat="50.93057371711882" lon="-1.4172013589758379">
+ </trkpt>
+ <trkpt lat="50.927827693921735" lon="-1.4161009227527916">
+ </trkpt>
+ <trkpt lat="50.924214426906204" lon="-1.4149669366245365">
+ </trkpt>
+ <trkpt lat="50.92130471816014" lon="-1.4151357012894712">
+ </trkpt>
+ <trkpt lat="50.921575004246044" lon="-1.4176606404849228">
+ </trkpt>
+ <trkpt lat="50.92238585308297" lon="-1.4196297754549603">
+ </trkpt>
+ <trkpt lat="50.9233868815378" lon="-1.42097958571668">
+ </trkpt>
+ </trkseg>
+ </trk>
+</gpx> \ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..86f3813
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="menu_find">Find</string>
+ <string name="menu_preferences">Preferences</string>
+ <string name="menu_view">View</string>
+ <string name="menu_find_my_location">Find my Location</string>
+ <string name="app_name">Southampton University Map</string>
+ <string name="legal_message">Southampton University Map comes with ABSOLUTELY NO WARRANTY; do not rely on the data or functionality provided by this application. This is free software, and you are welcome to redistribute it under certain conditions; expand the Licence item above for more details.</string>
+ <string name="building_residential">Residential Building</string>
+ <string name="building_non_residential">Non-Residential Building</string>
+ <string name="pref_bus_stop">Bus Stops</string>
+ <string name="U1">U1</string>
+ <string name="U1N">U1N</string>
+ <string name="U2">U2</string>
+ <string name="U6">U6</string>
+ <string name="U9">U9</string>
+ <string name="menu_about">About</string>
+ <string name="menu_favourites">Favourites</string>
+
+ <!-- Preferences Messages -->
+ <string name="map_help_message">You can drag the map to move it, you can use pinch motions to zoom in and out, this can also be done with the buttons at the bottom of the screen. Taping the building markers will show you there full name, and tapping the bus stop markers will show the live times at that stop. Presing and holding a marker, will add the item to the favourites list.</string>
+ <string name="find_help_message">The Find screen allows you to search for buildings, bus stops and sites. You can search by description and id. If your location is known, the results will be sorted by distance from your current location.</string>
+ <string name="preferences_help_message">You can disable and enable the apps use of live bus times and gps positioning from the preferences screen.</string>
+ <string name="findmylocation_help_message">When you press the Find my Location button on the menu, the map view will move to your location, and zoom in.</string>
+ <string name="view_help_message">Use the options in the View dialog to enable and disable the map elements.</string>
+ <string name="about_help_message">The About screen displays the help messages and also the contact details of the developer. You also have the option of making a Bitcoin donation using the Donate button at the bottom. WARNING, the donation address is not private as it is hardcoded in to the app.</string>
+ <string name="favourites_help_message">The favourites dialog includes a list of buildings or bus stops marked as favourites, this is meant to allow for easier access to frequently used locations.</string>
+ <string name="licence_help_message">Southampton University Map App Copyright © 2011 Christopher Baines\n
+\n
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.\n
+\n
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.\n
+\n
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</string>
+ <string name="credits_help_message">Software Design: Christopher Banines cbaines8@gmail.com Live Bus Data: provided under the Open Government License by the Southampton City Council ROMANSE office through the University of Southampton Open Data Service. Data: From the OpenStreetMap project, exported and used from the University of Southampton Open Data Service. Map Icons: From the "Map Icons Collection" (http://mapicons.nicolasmollet.com). Map Tiles: From the Mapnik project, through the OSMDroid libary. Database: Using the ORMLite libary.</string>
+ <string name="donate_button">Donate</string>
+ <string name="bitcoin_error_message">You appear to have no bitcoin client installed, or at least none that listen for bitcoin uri\'s. Either install such a client, or just send coins via any method from any device to the address below.</string>
+ <string name="preferences">Preferences</string>
+
+ <string-array name="uniLinkBusRoutes">
+ <item>U1</item>
+ <item>U1N</item>
+ <item>U2</item>
+ <item>U6</item>
+ <item>U9</item>
+ </string-array>
+ <string-array name="buildingTypes">
+ <item>Residential</item>
+ <item>Non-Residential</item>
+ </string-array>
+ <string-array name="utilityOverlays">
+ <item>Scale Bar</item>
+ <item>Compass</item>
+ <item>My Location</item>
+ </string-array>
+ <string-array name="preferencesHeadings">
+ <item>Bus Stops</item>
+ <item>Bus Routes</item>
+ <item>Buildings</item>
+ <item>Site Outlines</item>
+ <item>Other</item>
+ </string-array>
+
+ <string name="preferences_catagory_positioning">Positioning</string>
+ <string name="preferences_gps_enabled">GPS Enabled</string>
+ <string name="preferences_gps_disabled">GPS Disabled</string>
+ <string name="preferences_catagory_bus_times">Bus Times</string>
+ <string name="preferences_live_bus_times_enabled">Live Bus Times Enabled</string>
+ <string name="preferences_live_bus_times_disabled">Live Bus Times Disabled</string>
+ <string name="about_menu_instruction_text">Expand the items below to learn more about each feature of the application.</string>
+ <string name="bustimes_favourite_checkbox_label">Favourite</string>
+ <string name="donate_dialog_message">Loading bitcoin client</string>
+ <string name="donate_dialog_error_title">Error</string>
+
+</resources> \ No newline at end of file
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
new file mode 100644
index 0000000..51f176c
--- /dev/null
+++ b/res/xml/preferences.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <PreferenceCategory
+ android:orderingFromXml="true"
+ android:title="@string/preferences_catagory_positioning" >
+ <CheckBoxPreference
+ android:key="GPSEnabled"
+ android:summaryOff="@string/preferences_gps_disabled"
+ android:summaryOn="@string/preferences_gps_enabled"
+ android:title="GPS" />
+ </PreferenceCategory>
+ <PreferenceCategory
+ android:orderingFromXml="true"
+ android:title="@string/preferences_catagory_bus_times" >
+ <CheckBoxPreference
+ android:key="liveBusTimesEnabled"
+ android:summaryOff="@string/preferences_live_bus_times_disabled"
+ android:summaryOn="@string/preferences_live_bus_times_enabled"
+ android:title="Live Bus Times" />
+ </PreferenceCategory>
+
+</PreferenceScreen> \ No newline at end of file
diff --git a/src/net/cbaines/suma/AboutActivity.java b/src/net/cbaines/suma/AboutActivity.java
new file mode 100644
index 0000000..b330596
--- /dev/null
+++ b/src/net/cbaines/suma/AboutActivity.java
@@ -0,0 +1,149 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.Button;
+import android.widget.ExpandableListView;
+import android.widget.TextView;
+
+public class AboutActivity extends Activity implements OnClickListener {
+
+ static final int DONATE_DIALOG_ID = 0;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.about_dialog);
+
+ ExpandableListView epView = (ExpandableListView) findViewById(R.id.helpExpandableListView);
+ AboutListAdapter mAdapter = new AboutListAdapter(this);
+ epView.setAdapter(mAdapter);
+
+ Button donateButton = (Button) findViewById(R.id.donateButton);
+ donateButton.setOnClickListener(this);
+
+ }
+
+ class AboutListAdapter extends BaseExpandableListAdapter {
+ private String[] groups = { "Map", "Find", "Preferences", "Find my Location", "View", "About", "Favourites", "Licence", "Credits" };
+ private LayoutInflater inflater;
+ private Context cxt;
+
+ public AboutListAdapter(Context cxt) {
+ inflater = LayoutInflater.from(cxt);
+ this.cxt = cxt;
+ }
+
+ public Object getChild(int groupPos, int childPos) {
+ if (groupPos == 0) {
+ return cxt.getResources().getString(R.string.map_help_message);
+ } else if (groupPos == 1) {
+ return cxt.getResources().getString(R.string.find_help_message);
+ } else if (groupPos == 1) {
+ return cxt.getResources().getString(R.string.preferences_help_message);
+ } else if (groupPos == 2) {
+ return cxt.getResources().getString(R.string.findmylocation_help_message);
+ } else if (groupPos == 3) {
+ return cxt.getResources().getString(R.string.view_help_message);
+ } else if (groupPos == 4) {
+ return cxt.getResources().getString(R.string.about_help_message);
+ } else if (groupPos == 5) {
+ return cxt.getResources().getString(R.string.favourites_help_message);
+ } else if (groupPos == 6) {
+ return cxt.getResources().getString(R.string.favourites_help_message);
+ } else if (groupPos == 7) {
+ return cxt.getResources().getString(R.string.licence_help_message);
+ } else if (groupPos == 8) {
+ return cxt.getResources().getString(R.string.credits_help_message);
+ }
+ return null;
+ }
+
+ public long getChildId(int groupPos, int childPos) {
+ return childPos;
+ }
+
+ public View getChildView(int groupPos, int childPos, boolean isLastChild, View convertView, ViewGroup parent) {
+ TextView tv = new TextView(cxt);
+ tv.setText(getChild(groupPos, childPos).toString());
+ return tv;
+ }
+
+ public int getChildrenCount(int groupPos) {
+ return 1;
+ }
+
+ public Object getGroup(int groupPos) {
+ return groups[groupPos];
+ }
+
+ public int getGroupCount() {
+ return groups.length;
+ }
+
+ public long getGroupId(int groupPos) {
+ return groupPos;
+ }
+
+ public View getGroupView(int groupPos, boolean isExpanded, View convertView, ViewGroup parent) {
+ View v = null;
+ if (convertView != null)
+ v = convertView;
+ else
+ v = inflater.inflate(R.layout.view_group_row, parent, false);
+ String gt = (String) getGroup(groupPos);
+ TextView colorGroup = (TextView) v.findViewById(R.id.childname);
+ if (gt != null)
+ colorGroup.setText(gt);
+ return v;
+ }
+
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ public boolean isChildSelectable(int groupPos, int childPos) {
+ return true;
+ }
+
+ }
+
+ public void onClick(View arg0) {
+ showDialog(DONATE_DIALOG_ID);
+ }
+
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DONATE_DIALOG_ID:
+ DonateDialog donateDialog = new DonateDialog(this);
+ return donateDialog;
+
+ }
+ return null;
+ }
+}
diff --git a/src/net/cbaines/suma/Building.java b/src/net/cbaines/suma/Building.java
new file mode 100644
index 0000000..df8c303
--- /dev/null
+++ b/src/net/cbaines/suma/Building.java
@@ -0,0 +1,64 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import org.osmdroid.util.GeoPoint;
+
+import com.j256.ormlite.field.DataType;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "buildings")
+public class Building extends POI {
+ public static final String NAME_FIELD_NAME = "name";
+ public static final String RESIDENTIAL_FIELD_NAME = "residential";
+ public static final String OUTLINE_FIELD_NAME = "outline";
+
+ @DatabaseField(canBeNull = false)
+ public String name;
+ @DatabaseField(canBeNull = false)
+ boolean residential;
+ @DatabaseField(dataType = DataType.SERIALIZABLE, canBeNull = true)
+ Polygon outline;
+
+ Building(String id, GeoPoint point, boolean residential, String name, Polygon outline) {
+ super(id, point);
+ this.residential = residential;
+ this.name = name;
+ this.outline = outline;
+ this.type = POI.BUILDING;
+ }
+
+ Building(String id, GeoPoint point, boolean residential, String name) {
+ this(id, point, residential, name, null);
+ }
+
+ Building(String id, GeoPoint point, boolean residential) {
+ this(id, point, residential, "");
+ }
+
+ Building() {
+ this.type = POI.BUILDING;
+ }
+
+ public String toString() {
+ return name + " (" + id + ")";
+ }
+}
diff --git a/src/net/cbaines/suma/BuildingNumOverlay.java b/src/net/cbaines/suma/BuildingNumOverlay.java
new file mode 100644
index 0000000..080cdc6
--- /dev/null
+++ b/src/net/cbaines/suma/BuildingNumOverlay.java
@@ -0,0 +1,273 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.MapView.Projection;
+import org.osmdroid.views.overlay.Overlay;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.widget.Toast;
+
+import com.j256.ormlite.android.apptools.OpenHelperManager;
+import com.j256.ormlite.dao.Dao;
+
+public class BuildingNumOverlay extends Overlay {
+
+ private ArrayList<Building> buildings;
+
+ private final Point mCurScreenCoords = new Point();
+ private final Point mTouchScreenPoint = new Point();
+ private final Point mItemPoint = new Point();
+
+ private final Rect mRect = new Rect();
+
+ private final Drawable marker;
+ private final Drawable favMarker;
+
+ private final Paint paint;
+
+ private static final String TAG = "BuildingNumOverlay";
+
+ private final Context context;
+
+ private Dao<Building, String> buildingDao;
+
+ private float userScale = 1f;
+
+ public BuildingNumOverlay(Context context, List<Building> buildings) throws SQLException {
+ super(context);
+
+ this.context = context;
+
+ marker = context.getResources().getDrawable(R.drawable.building);
+ favMarker = context.getResources().getDrawable(R.drawable.building_fav);
+
+ DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+ buildingDao = helper.getBuildingDao();
+
+ paint = new Paint();
+ paint.setColor(Color.BLACK);
+ paint.setAntiAlias(true);
+ paint.setStyle(Style.FILL);
+ paint.setAlpha(120);
+ paint.setStrokeWidth(6);
+ paint.setTextAlign(Paint.Align.CENTER);
+
+ this.buildings = (ArrayList<Building>) buildings;
+ }
+
+ /**
+ * Draw a marker on each of our items. populate() must have been called first.<br/>
+ * <br/>
+ * The marker will be drawn twice for each Item in the Overlay--once in the shadow phase, skewed and darkened, then again in the non-shadow phase. The
+ * bottom-center of the marker will be aligned with the geographical coordinates of the Item.<br/>
+ * <br/>
+ * The order of drawing may be changed by overriding the getIndexToDraw(int) method. An item may provide an alternate marker via its
+ * OverlayItem.getMarker(int) method. If that method returns null, the default marker is used.<br/>
+ * <br/>
+ * The focused item is always drawn last, which puts it visually on top of the other items.<br/>
+ *
+ * @param canvas
+ * the Canvas upon which to draw. Note that this may already have a transformation applied, so be sure to leave it the way you found it
+ * @param mapView
+ * the MapView that requested the draw. Use MapView.getProjection() to convert between on-screen pixels and latitude/longitude pairs
+ * @param shadow
+ * if true, draw the shadow layer. If false, draw the overlay contents.
+ */
+ @Override
+ public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
+
+ if (shadow) {
+ return;
+ }
+
+ float scale = mScale * userScale;
+
+ final Projection pj = mapView.getProjection();
+
+ final int markerWidth = (int) (marker.getIntrinsicWidth() * userScale);
+ final int markerHeight = (int) (marker.getIntrinsicHeight() * userScale);
+
+ mRect.set(0, 0, 0 + markerWidth, 0 + markerHeight);
+ mRect.offset(-markerWidth / 2, -markerHeight);
+ marker.setBounds(mRect);
+ favMarker.setBounds(mRect);
+
+ /* Draw in backward cycle, so the items with the least index are on the front. */
+ for (Iterator<Building> buildingIter = buildings.iterator(); buildingIter.hasNext();) {
+ final Building building = buildingIter.next();
+
+ // Log.i(TAG, "Looking at drawing stop " + stop.id);
+
+ pj.toMapPixels(building.point, mCurScreenCoords);
+
+ // draw it
+ if (building.favourite) {
+ Overlay.drawAt(canvas, favMarker, mCurScreenCoords.x, mCurScreenCoords.y, false);
+ } else {
+ Overlay.drawAt(canvas, marker, mCurScreenCoords.x, mCurScreenCoords.y, false);
+ }
+
+ String idString = String.valueOf(building.id);
+
+ int yOfset = 10;
+ switch (idString.length()) {
+ case 1:
+ paint.setTextSize(25 * scale);
+ yOfset = 18;
+ break;
+ case 2:
+ paint.setTextSize(24 * scale);
+ yOfset = 18;
+ break;
+ case 3:
+ paint.setTextSize(17 * scale);
+ yOfset = 20;
+ break;
+ case 4:
+ paint.setTextSize(14 * scale);
+ yOfset = 23;
+ break;
+ case 5:
+ paint.setTextSize(10 * scale);
+ yOfset = 20;
+ break;
+ case 6:
+ paint.setTextSize(9 * scale);
+ yOfset = 24;
+ break;
+ default:
+ Log.w(TAG, "Reverting to default text size for length " + idString.length());
+ paint.setTextSize(15 * scale);
+ break;
+ }
+ canvas.drawText(idString, mCurScreenCoords.x, mCurScreenCoords.y - (yOfset * scale), paint);
+ }
+ }
+
+ @Override
+ public boolean onSingleTapUp(final MotionEvent event, final MapView mapView) {
+ if (!this.isEnabled())
+ return false;
+
+ final Building building = getSelectedItem(event, mapView);
+
+ if (building == null) {
+ Log.i(TAG, "No building pressed");
+ return false;
+ } else {
+ Log.i(TAG, "building Pressed " + building.id);
+
+ Toast.makeText(context, building.name + " (" + building.id + ")", Toast.LENGTH_SHORT).show();
+ return true;
+ }
+
+ }
+
+ @Override
+ public boolean onLongPress(final MotionEvent event, final MapView mapView) {
+ if (!this.isEnabled())
+ return false;
+
+ final Building building = getSelectedItem(event, mapView);
+
+ if (building == null) {
+ Log.i(TAG, "No building pressed");
+ return false;
+ } else {
+ Log.i(TAG, "building Pressed " + building.id);
+
+ if (building.favourite) {
+ building.favourite = false;
+
+ Toast.makeText(context, building.id + " removed from favourites", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(context, building.id + " made a favourite", Toast.LENGTH_SHORT).show();
+
+ building.favourite = true;
+ }
+
+ try {
+ buildingDao.update(building);
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ Collections.sort(buildings, new POIFavouriteComparator());
+
+ mapView.invalidate();
+
+ return true;
+ }
+
+ }
+
+ private Building getSelectedItem(final MotionEvent event, final MapView mapView) {
+ final Projection pj = mapView.getProjection();
+ final int eventX = (int) event.getX();
+ final int eventY = (int) event.getY();
+
+ /* These objects are created to avoid construct new ones every cycle. */
+ pj.fromMapPixels(eventX, eventY, mTouchScreenPoint);
+
+ // Iterate back through the array to properly deal with overlap
+ for (int i = buildings.size() - 1; i > 0; i--) {
+ final Building building = buildings.get(i);
+
+ pj.toPixels(building.point, mItemPoint);
+
+ if (marker.getBounds().contains(mTouchScreenPoint.x - mItemPoint.x, mTouchScreenPoint.y - mItemPoint.y)) {
+ return building;
+ }
+ }
+ return null;
+ }
+
+ public void refresh() {
+ for (int i = 0; i < buildings.size(); i++) {
+ refresh(buildings.get(i));
+ }
+ }
+
+ public void refresh(Building building) {
+ if (building.favourite) {
+ buildings.remove(building);
+ buildings.add(building);
+ }
+ }
+
+}
diff --git a/src/net/cbaines/suma/Bus.java b/src/net/cbaines/suma/Bus.java
new file mode 100644
index 0000000..c73d6d7
--- /dev/null
+++ b/src/net/cbaines/suma/Bus.java
@@ -0,0 +1,57 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "buses")
+public class Bus {
+
+ @DatabaseField(id = true)
+ int id;
+
+ @DatabaseField(canBeNull = true, foreign = true)
+ Stop lastKnownStop;
+
+ @DatabaseField(canBeNull = true, foreign = true)
+ Stop firstKnownStop;
+
+ @DatabaseField(canBeNull = false, foreign = true)
+ BusRoute lastKnownRoute;
+
+ Bus() {
+ }
+
+ Bus(int id, BusRoute lastKnownRoute, Stop lastKnownStop) {
+ this.id = id;
+ this.lastKnownRoute = lastKnownRoute;
+ this.lastKnownStop = lastKnownStop;
+ }
+
+ Bus(int id, BusRoute lastKnownRoute) {
+ this(id, lastKnownRoute, null);
+ }
+
+ public String toString() {
+ return String.valueOf(id);
+ }
+
+}
diff --git a/src/net/cbaines/suma/BusRoute.java b/src/net/cbaines/suma/BusRoute.java
new file mode 100644
index 0000000..016f3bd
--- /dev/null
+++ b/src/net/cbaines/suma/BusRoute.java
@@ -0,0 +1,186 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.j256.ormlite.android.apptools.OpenHelperManager;
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.stmt.PreparedQuery;
+import com.j256.ormlite.stmt.QueryBuilder;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "busroutes")
+/**
+ * This class represents a bus route (U1, U1N, ..).
+ *
+ * @author Christopher Baines <cbaines8@gmail.com>
+ *
+ */
+public class BusRoute {
+
+ final static String ID_FIELD_NAME = "id";
+ final static String CODE_FIELD_NAME = "code";
+ final static String LABEL_FIELD_NAME = "label";
+
+ private static final String TAG = "BusRoute";
+
+ @DatabaseField(id = true)
+ int id;
+
+ @DatabaseField
+ String code;
+
+ @DatabaseField
+ String label;
+
+ BusRoute() {
+ }
+
+ BusRoute(Integer id, String code, String label) {
+ this.id = id.intValue();
+ this.code = code;
+ this.label = label;
+ }
+
+ public String toString() {
+ return code;
+ }
+
+ /**
+ * Untested?
+ *
+ * @param context
+ * @param stop
+ * @return
+ */
+ BusStop getBusStopBefore(Context context, Stop stop) {
+ return moveInRoute(context, stop, -1);
+ }
+
+ /**
+ * Untested?
+ *
+ * @param context
+ * @param stop
+ * @return
+ */
+ BusStop getStopAfter(Context context, Stop stop) {
+ return moveInRoute(context, stop, 1);
+ }
+
+ /**
+ * Untested?
+ *
+ * @param context
+ * @param stop
+ * @param moveAmount
+ * @return
+ */
+ BusStop moveInRoute(Context context, Stop stop, int moveAmount) {
+ DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+
+ try {
+ Dao<RouteStops, Integer> routeStopsDao = helper.getRouteStopsDao();
+ // Dao<Stop, Integer> stopDao = helper.getStopDao();
+ Dao<BusStop, String> busStopDao = helper.getBusStopDao();
+
+ int stopSeq;
+ int beforeStopSeq = -1;
+
+ QueryBuilder<RouteStops, Integer> routeStopsQueryBuilder = routeStopsDao.queryBuilder();
+ routeStopsQueryBuilder.where().eq(RouteStops.ROUTE_ID_FIELD_NAME, this.id).and().eq(RouteStops.STOP_ID_FIELD_NAME, stop.busStop.id);
+ PreparedQuery<RouteStops> routeStopsPreparedQuery = routeStopsQueryBuilder.prepare();
+
+ List<RouteStops> stopsFound = routeStopsDao.query(routeStopsPreparedQuery);
+ if (stopsFound.size() != 0) {
+ Log.e(TAG, "Wierd, found more than one stop");
+ return null;
+ }
+
+ long maxSeq = 0;
+
+ routeStopsQueryBuilder = routeStopsDao.queryBuilder();
+ routeStopsQueryBuilder.where().eq(RouteStops.ROUTE_ID_FIELD_NAME, this.id);
+ routeStopsQueryBuilder.setCountOf(true);
+ routeStopsPreparedQuery = routeStopsQueryBuilder.prepare();
+
+ maxSeq = routeStopsDao.countOf(routeStopsPreparedQuery);
+
+ if (maxSeq == 0) {
+ Log.e(TAG, "Something wierd has gone on, maxSeq equals 0");
+ return null;
+ }
+
+ if (id == 326) { // U1
+
+ if (stop.name.equals("U1C")) {// Seq 0 = End of route
+
+ stopSeq = routeStopsDao.query(routeStopsPreparedQuery).get(0).sequence;
+
+ beforeStopSeq = stopSeq + moveAmount;
+
+ } else if (stop.name.equals("U1A")) { // seq 88 == end of route
+
+ stopSeq = routeStopsDao.query(routeStopsPreparedQuery).get(0).sequence;
+
+ beforeStopSeq = stopSeq - moveAmount;
+
+ } else {
+ Log.e(TAG, "In route U1 but " + stop.name + " does not match U1A or U1C");
+ return null;
+ }
+ } else {
+ Log.e(TAG, "Route id not recognised " + id);
+ return null;
+ }
+
+ if (beforeStopSeq == -1) {
+ Log.e(TAG, "Something wierd has gone on, beforeStopSeq equals -1");
+ return null;
+ }
+
+ routeStopsQueryBuilder = routeStopsDao.queryBuilder();
+ routeStopsQueryBuilder.where().eq(RouteStops.ROUTE_ID_FIELD_NAME, this.id).and().eq(RouteStops.SEQUENCE_ID_FIELD_NAME, beforeStopSeq);
+
+ routeStopsPreparedQuery = routeStopsQueryBuilder.prepare();
+
+ List<RouteStops> beforeStopsFound = routeStopsDao.query(routeStopsPreparedQuery);
+ if (stopsFound.size() != 0) {
+ Log.e(TAG, "Wierd, found more than one before stop");
+ return null;
+ }
+
+ busStopDao.refresh(beforeStopsFound.get(0).stop);
+
+ return beforeStopsFound.get(0).stop;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+}
diff --git a/src/net/cbaines/suma/BusStop.java b/src/net/cbaines/suma/BusStop.java
new file mode 100644
index 0000000..8e13f27
--- /dev/null
+++ b/src/net/cbaines/suma/BusStop.java
@@ -0,0 +1,57 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import org.osmdroid.util.GeoPoint;
+
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "busstops")
+public class BusStop extends POI {
+ public static final String DESCRIPTION_FIELD_NAME = "description";
+ public static final String BAY_FIELD_NAME = "bay";
+ public static final String ROUTES_FIELD_NAME = "bay";
+
+ @DatabaseField(canBeNull = true)
+ public String description;
+ @DatabaseField(canBeNull = true)
+ public String bay;
+
+ // Used to speed up accessing the relevent uni link routes for a bus stop, if == 0, this is not a uni link stop
+ @DatabaseField(canBeNull = false)
+ byte routes;
+
+ BusStop(String location, String description, String bay, GeoPoint point) {
+ this.id = location;
+ this.description = description;
+ this.bay = bay;
+ this.point = point;
+ this.type = POI.BUS_STOP;
+ }
+
+ BusStop() {
+ this.type = POI.BUS_STOP;
+ }
+
+ public String toString() {
+ return description + " (" + id + ")";
+ }
+}
diff --git a/src/net/cbaines/suma/BusStopOverlay.java b/src/net/cbaines/suma/BusStopOverlay.java
new file mode 100644
index 0000000..69687b6
--- /dev/null
+++ b/src/net/cbaines/suma/BusStopOverlay.java
@@ -0,0 +1,309 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.MapView.Projection;
+import org.osmdroid.views.overlay.Overlay;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.widget.Toast;
+
+import com.j256.ormlite.android.apptools.OpenHelperManager;
+import com.j256.ormlite.dao.Dao;
+
+public class BusStopOverlay extends Overlay implements RouteColorConstants {
+
+ private ArrayList<BusStop> busStops;
+
+ private final Point mCurScreenCoords = new Point();
+ private final Point mTouchScreenPoint = new Point();
+ private final Point mItemPoint = new Point();
+
+ private final Rect mRect = new Rect();
+
+ private final Drawable marker;
+ private final Drawable favMarker;
+
+ private final Paint paint;
+
+ private static final String TAG = "BusStopOverlay";
+
+ private final Context context;
+
+ private Dao<BusStop, String> busStopDao;
+
+ private float userScale = 1f;
+
+ private boolean[] routes = new boolean[5];
+
+ public BusStopOverlay(Context context) throws SQLException {
+ super(context);
+
+ this.context = context;
+
+ marker = context.getResources().getDrawable(R.drawable.busstop);
+ favMarker = context.getResources().getDrawable(R.drawable.busstop_fav);
+
+ DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+ busStopDao = helper.getBusStopDao();
+
+ paint = new Paint();
+ paint.setStyle(Style.FILL);
+ paint.setStrokeWidth(6);
+
+ busStops = new ArrayList<BusStop>((int) busStopDao.countOf());
+ busStops.addAll(busStopDao.queryForAll());
+ }
+
+ void setRoutes(int route, boolean visible) {
+ routes[route] = visible;
+ }
+
+ @Override
+ public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
+
+ if (shadow) {
+ return;
+ }
+
+ float scale = mScale * userScale;
+
+ final Projection pj = mapView.getProjection();
+
+ final int markerWidth = (int) (marker.getIntrinsicWidth() * userScale);
+ final int markerHeight = (int) (marker.getIntrinsicHeight() * userScale);
+
+ mRect.set(0, 0, 0 + markerWidth, 0 + markerHeight);
+ mRect.offset(-markerWidth / 2, -markerHeight);
+ marker.setBounds(mRect);
+ favMarker.setBounds(mRect);
+
+ /* Draw in backward cycle, so the items with the least index are on the front. */
+
+ for (int stopNum = 0; stopNum < busStops.size(); stopNum++) {
+ BusStop stop = busStops.get(stopNum);
+
+ final byte stopRoutes = stop.routes;
+ byte routeNum = 0;
+ boolean drawing = false;
+
+ for (int i = 0; i < 5; i++) {
+ if ((stopRoutes & (1 << i)) != 0) {
+ routeNum++;
+ if (routes[i]) {
+ drawing = true;
+ }
+ }
+ }
+
+ if (!drawing)
+ continue;
+
+ int yOfsetPerMarker = (int) (10 * scale);
+ int markerYSize = (int) (8 * scale);
+
+ pj.toMapPixels(stop.point, mCurScreenCoords);
+
+ if (stop.favourite) {
+ Overlay.drawAt(canvas, favMarker, mCurScreenCoords.x, mCurScreenCoords.y, false);
+ } else {
+ Overlay.drawAt(canvas, marker, mCurScreenCoords.x, mCurScreenCoords.y, false);
+ }
+ // Log.i(TAG, "Got " + routes.size() + " routes " + routes);
+
+ int makersPlaced = 0;
+
+ float rectLeft = mCurScreenCoords.x + (8.8f * scale);
+ float rectRight = rectLeft + markerYSize;
+
+ if (routeNum == 5) {
+ markerYSize = (int) (5 * scale);
+ yOfsetPerMarker = (int) (7 * scale);
+ } else if (routeNum == 4) {
+ markerYSize = (int) (6.5f * scale);
+ yOfsetPerMarker = (int) (8 * scale);
+ }
+
+ for (int i = 0; i < 5; i++) {
+ if ((stopRoutes & (1 << i)) != 0) {
+
+ // Log.i(TAG, "Route " + route + " is " + routes.get(route));
+
+ // Log.i(TAG, "Index is " + busRoutes.indexOf(route) + " busRoutes " + busRoutes);
+
+ if (i == 0) {
+ paint.setColor(U1);
+ } else if (i == 1) {
+ paint.setColor(U1N);
+ } else if (i == 2) {
+ paint.setColor(U2);
+ } else if (i == 3) {
+ paint.setColor(U6);
+ } else if (i == 4) {
+ paint.setColor(U9);
+ } else {
+ Log.e(TAG, "Unknown route code");
+ }
+
+ canvas.drawRect(rectLeft, mCurScreenCoords.y + ((yOfsetPerMarker * makersPlaced) - (45 * scale)), rectRight, mCurScreenCoords.y
+ + (yOfsetPerMarker * makersPlaced) - ((45 * scale) - markerYSize), paint);
+
+ makersPlaced++;
+ }
+ }
+
+ }
+ }
+
+ @Override
+ public boolean onSingleTapUp(final MotionEvent event, final MapView mapView) {
+
+ BusStop busStop = getSelectedItem(event, mapView);
+
+ if (busStop == null) {
+ Log.i(TAG, "No busStop pressed");
+
+ return false;
+ } else {
+ Log.i(TAG, "Pressed " + busStop.id);
+
+ Intent i = new Intent(context, BusTimeActivity.class);
+ i.putExtra("busStopID", busStop.id);
+ i.putExtra("busStopName", busStop.description);
+ ((Activity) context).startActivityForResult(i, 0);
+
+ return true;
+ }
+
+ }
+
+ @Override
+ public boolean onLongPress(final MotionEvent event, final MapView mapView) {
+ BusStop busStop = getSelectedItem(event, mapView);
+
+ if (busStop == null) {
+ Log.i(TAG, "No busStop pressed");
+ return false;
+ } else {
+ Log.i(TAG, "Pressed " + busStop.id);
+
+ if (busStop.favourite) {
+ busStop.favourite = false;
+
+ Toast.makeText(context, busStop.id + " removed from favourites", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(context, busStop.id + " made a favourite", Toast.LENGTH_SHORT).show();
+
+ busStop.favourite = true;
+ }
+
+ try {
+ busStopDao.update(busStop);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ Collections.sort(busStops, new POIFavouriteComparator());
+
+ mapView.invalidate();
+
+ return true;
+ }
+
+ }
+
+ public void refresh() {
+ try {
+ for (int i = 0; i < busStops.size(); i++) {
+ BusStop busStop = busStops.get(i);
+ busStopDao.refresh(busStop);
+ if (busStop.favourite) {
+ busStops.remove(i);
+ busStops.add(busStop);
+ } else {
+ busStops.set(i, busStop);
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Replaces any bus stops that equal the argument in the overlay with the argument
+ *
+ * @param busStop
+ */
+ public void refresh(BusStop busStop) {
+ for (int i = 0; i < busStops.size(); i++) {
+ if (busStop.equals(busStops.get(i))) {
+ busStops.set(i, busStop);
+ }
+ }
+ }
+
+ private BusStop getSelectedItem(final MotionEvent event, final MapView mapView) {
+ final Projection pj = mapView.getProjection();
+ final int eventX = (int) event.getX();
+ final int eventY = (int) event.getY();
+
+ /* These objects are created to avoid construct new ones every cycle. */
+ pj.fromMapPixels(eventX, eventY, mTouchScreenPoint);
+
+ for (int i = busStops.size() - 1; i > 0; i--) {
+ BusStop busStop = busStops.get(i);
+
+ pj.toPixels(busStop.point, mItemPoint);
+
+ if (marker.getBounds().contains(mTouchScreenPoint.x - mItemPoint.x, mTouchScreenPoint.y - mItemPoint.y)) {
+ boolean drawing = false;
+ for (int route = 0; route < 5; route++) {
+ if ((busStop.routes & (1 << route)) != 0) {
+ if (routes[route]) {
+ drawing = true;
+ break;
+ }
+ }
+ }
+ if (!drawing)
+ continue;
+
+ return busStop;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/src/net/cbaines/suma/BusStopView.java b/src/net/cbaines/suma/BusStopView.java
new file mode 100644
index 0000000..d76198b
--- /dev/null
+++ b/src/net/cbaines/suma/BusStopView.java
@@ -0,0 +1,34 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import android.content.Context;
+
+public class BusStopView extends POIView {
+
+ public BusStopView(Context context, BusStop busStop) {
+ this(context, busStop, -1);
+ }
+
+ public BusStopView(Context context, BusStop busStop, int dist) {
+ super(context, (POI) busStop, dist);
+ }
+
+}
diff --git a/src/net/cbaines/suma/BusTimeActivity.java b/src/net/cbaines/suma/BusTimeActivity.java
new file mode 100644
index 0000000..be8b14a
--- /dev/null
+++ b/src/net/cbaines/suma/BusTimeActivity.java
@@ -0,0 +1,247 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.sql.SQLException;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.j256.ormlite.android.apptools.OrmLiteBaseActivity;
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.stmt.PreparedQuery;
+import com.j256.ormlite.stmt.QueryBuilder;
+
+public class BusTimeActivity extends OrmLiteBaseActivity<DatabaseHelper> implements Runnable, OnCheckedChangeListener {
+
+ final static String TAG = "BusTimeActivity";
+
+ private boolean dataChanged;
+
+ private ListView busTimeList;
+ private TextView busName;
+ private TextView busID;
+ private CheckBox busFavourite;
+ private TextView busStopMessage;
+ private ProgressBar progBar;
+ private LinearLayout busTimeContentLayout;
+
+ private TimetableAdapter adapter;
+
+ private String busStopID;
+ private String busStopName;
+
+ private Dao<BusStop, String> busStopDao;
+
+ private BusStop busStop;
+
+ private Thread timetableThread;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.bustimes);
+
+ DatabaseHelper helper = getHelper();
+
+ busStopID = getIntent().getExtras().getString("busStopID");
+ busStopName = getIntent().getExtras().getString("busStopName");
+
+ TextView U1RouteTextView = (TextView) findViewById(R.id.busStopU1);
+ TextView U1NRouteTextView = (TextView) findViewById(R.id.busStopU1N);
+ TextView U2RouteTextView = (TextView) findViewById(R.id.busStopU2);
+ TextView U6RouteTextView = (TextView) findViewById(R.id.busStopU6);
+ TextView U9RouteTextView = (TextView) findViewById(R.id.busStopU9);
+
+ try {
+ Dao<BusRoute, Integer> busRouteDao = helper.getBusRouteDao();
+ Dao<RouteStops, Integer> routeStopsDao = helper.getRouteStopsDao();
+
+ for (BusRoute route : busRouteDao) {
+ QueryBuilder<RouteStops, Integer> queryBuilder = routeStopsDao.queryBuilder();
+
+ queryBuilder.where().eq(RouteStops.ROUTE_ID_FIELD_NAME, route.id).and().eq(RouteStops.STOP_ID_FIELD_NAME, busStopID);
+ queryBuilder.setCountOf(true);
+ PreparedQuery<RouteStops> preparedQuery = queryBuilder.prepare();
+
+ long count = routeStopsDao.countOf(preparedQuery);
+
+ if (route.code.equals("U1")) {
+ if (count != 0) {
+ U1RouteTextView.setVisibility(View.VISIBLE);
+ } else {
+ U1RouteTextView.setVisibility(View.GONE);
+ }
+ } else if (route.code.equals("U1N")) {
+ if (count != 0) {
+ U1NRouteTextView.setVisibility(View.VISIBLE);
+ } else {
+ U1NRouteTextView.setVisibility(View.GONE);
+ }
+ } else if (route.code.equals("U2")) {
+ if (count != 0) {
+ U2RouteTextView.setVisibility(View.VISIBLE);
+ } else {
+ U2RouteTextView.setVisibility(View.GONE);
+ }
+ } else if (route.code.equals("U6")) {
+ if (count != 0) {
+ U6RouteTextView.setVisibility(View.VISIBLE);
+ } else {
+ U6RouteTextView.setVisibility(View.GONE);
+ }
+ } else if (route.code.equals("U9")) {
+ if (count != 0) {
+ U9RouteTextView.setVisibility(View.VISIBLE);
+ } else {
+ U9RouteTextView.setVisibility(View.GONE);
+ }
+ } else {
+ Log.e(TAG, "Error unknown route " + route.code);
+ }
+
+ }
+
+ busStopDao = helper.getBusStopDao();
+
+ busStop = busStopDao.queryForId(busStopID);
+
+ busFavourite = (CheckBox) findViewById(R.id.favouriteCheckBox);
+ busFavourite.setChecked(busStop.favourite);
+ busFavourite.setOnCheckedChangeListener(this);
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ busName = (TextView) findViewById(R.id.busStopName);
+ busID = (TextView) findViewById(R.id.busStopID);
+
+ busStopMessage = (TextView) findViewById(R.id.busStopMessage);
+ progBar = (ProgressBar) findViewById(R.id.busStopLoadBar);
+ busTimeList = (ListView) findViewById(R.id.busStopTimes);
+ busTimeContentLayout = (LinearLayout) findViewById(R.id.busTimeContentLayout);
+
+ Log.i(TAG, "Got busstop id " + busStopID);
+
+ busName.setText(busStopName);
+ busID.setText(busStopID);
+
+ SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ if (sharedPrefs.getBoolean("liveBusTimesEnabled", false)) {
+ timetableThread = new Thread(this);
+ timetableThread.start();
+ } else {
+ progBar.setVisibility(View.GONE);
+ busStopMessage.setText("Live bus times disabled");
+ busStopMessage.setVisibility(View.VISIBLE);
+ }
+
+ }
+
+ public void finish() {
+ Log.i(TAG, "Stopping BusTimeActivity thread");
+ if (timetableThread != null) { // Could happen if live bus times are disabled
+ timetableThread.interrupt();
+ }
+
+ if (dataChanged) {
+ getIntent().putExtra("busStopChanged", busStopID);
+ }
+
+ setResult(RESULT_OK, getIntent());
+
+ super.finish();
+ }
+
+ public void run() {
+ while (true) {
+ try {
+ Timetable timetable = DataManager.getTimetable(this, busStopID, true);
+
+ Log.i(TAG, "Got timetable for " + busStopID);
+ if (timetable == null) {
+ Log.i(TAG, "Its null");
+ busTimeList.post(new Runnable() {
+ public void run() {
+ progBar.setVisibility(View.GONE);
+ busStopMessage.setText("Error fetching bus times");
+ busStopMessage.setVisibility(View.VISIBLE);
+ }
+ });
+ } else {
+ Log.i(TAG, "It contains " + timetable.size() + " stops");
+
+ if (timetable.size() == 0) {
+ busTimeList.post(new Runnable() {
+ public void run() {
+ progBar.setVisibility(View.GONE);
+ busStopMessage.setText("No Busses");
+ busStopMessage.setVisibility(View.VISIBLE);
+ }
+ });
+ } else {
+
+ adapter = new TimetableAdapter(this, timetable);
+
+ busTimeList.post(new Runnable() {
+ public void run() {
+ progBar.setVisibility(View.GONE);
+ busStopMessage.setVisibility(View.GONE);
+ busTimeList.setAdapter(adapter);
+ busTimeContentLayout.setGravity(Gravity.TOP);
+ }
+ });
+ }
+ }
+
+ } catch (SQLException e1) {
+ e1.printStackTrace();
+ }
+
+ try {
+ Thread.sleep(20000);
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Bus stop activity thread stoped");
+ break;
+ }
+ }
+ }
+
+ public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
+ busStop.favourite = arg1;
+ try {
+ busStopDao.update(busStop);
+ dataChanged = true;
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/net/cbaines/suma/DataHandler.java b/src/net/cbaines/suma/DataHandler.java
new file mode 100644
index 0000000..f6263da
--- /dev/null
+++ b/src/net/cbaines/suma/DataHandler.java
@@ -0,0 +1,114 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import org.osmdroid.ResourceProxy;
+import org.osmdroid.views.overlay.PathOverlay;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import android.util.Log;
+
+public class DataHandler extends DefaultHandler {
+
+ // this holds the data
+ private PathOverlay _data;
+
+ private int colour;
+ private ResourceProxy resProxy;
+
+ public DataHandler(int colour, ResourceProxy resProxy) {
+ this.colour = colour;
+ this.resProxy = resProxy;
+ }
+
+ /**
+ * Returns the data object
+ *
+ * @return
+ */
+ public PathOverlay getData() {
+ return _data;
+ }
+
+ /**
+ * This gets called when the xml document is first opened
+ *
+ * @throws SAXException
+ */
+ @Override
+ public void startDocument() throws SAXException {
+ _data = new PathOverlay(colour, resProxy);
+ }
+
+ /**
+ * Called when it's finished handling the document
+ *
+ * @throws SAXException
+ */
+ @Override
+ public void endDocument() throws SAXException {
+
+ }
+
+ /**
+ * This gets called at the start of an element. Here we're also setting the booleans to true if it's at that specific tag. (so we know where we are)
+ *
+ * @param namespaceURI
+ * @param localName
+ * @param qName
+ * @param atts
+ * @throws SAXException
+ */
+ @Override
+ public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+ if (localName.equals("trkpt")) {
+ Log.v("DataHandler", "Adding point to route overlay " + atts.getValue("lat") + " " + atts.getValue("lon"));
+ _data.addPoint(Util.csLatLongToGeoPoint(atts.getValue("lat"), atts.getValue("lon")));
+ }
+ }
+
+ /**
+ * Called at the end of the element. Setting the booleans to false, so we know that we've just left that tag.
+ *
+ * @param namespaceURI
+ * @param localName
+ * @param qName
+ * @throws SAXException
+ */
+ @Override
+ public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+
+ }
+
+ /**
+ * Calling when we're within an element. Here we're checking to see if there is any content in the tags that we're interested in and populating it in the
+ * Config object.
+ *
+ * @param ch
+ * @param start
+ * @param length
+ */
+ @Override
+ public void characters(char ch[], int start, int length) {
+
+ }
+}
diff --git a/src/net/cbaines/suma/DataManager.java b/src/net/cbaines/suma/DataManager.java
new file mode 100644
index 0000000..e910c8e
--- /dev/null
+++ b/src/net/cbaines/suma/DataManager.java
@@ -0,0 +1,726 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.osmdroid.ResourceProxy;
+import org.osmdroid.util.GeoPoint;
+import org.osmdroid.views.overlay.PathOverlay;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.j256.ormlite.android.apptools.OpenHelperManager;
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.stmt.PreparedQuery;
+import com.j256.ormlite.stmt.QueryBuilder;
+import com.j256.ormlite.table.TableUtils;
+
+public class DataManager {
+
+ final static String TAG = "DataManager";
+
+ final static String busStopUrl = "http://data.southampton.ac.uk/bus-stop/";
+
+ private static Context context;
+
+ private static DatabaseHelper helper;
+ private static Dao<BusRoute, Integer> busRoutes;
+ private static Dao<Bus, Integer> busDao;
+ private static Dao<BusStop, String> busStopDao;
+ private static Dao<Stop, Integer> stopDao;
+
+ public static void loadBuildings(Context context) throws SQLException, IOException {
+ DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+ Dao<Building, String> buildingDao = helper.getBuildingDao();
+
+ TableUtils.clearTable(helper.getConnectionSource(), Building.class);
+
+ Log.i(TAG, "Loading buildings from csv");
+
+ HashMap<String, GeoPoint> buildingPoints = new HashMap<String, GeoPoint>();
+ HashMap<String, Polygon> buildingPolys = new HashMap<String, Polygon>();
+
+ InputStream inputStream = context.getAssets().open("buildings_points.csv");
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ String strLine;
+ try {
+ String def = bufferedReader.readLine();
+ // Log.i(TAG, "Reading the definition " + def);
+
+ while ((strLine = bufferedReader.readLine()) != null) {
+ // Log.i(TAG, "Data: " + strLine);
+ String[] dataBits = strLine.split(",");
+ GeoPoint point = Util.csLatLongToGeoPoint(dataBits[2], dataBits[1]);
+ // Log.i(TAG, "Creating building with id " + dataBits[0] + " and " + point.getLatitudeE6() + " " + point.getLongitudeE6());
+ buildingPoints.put(dataBits[0], point);
+ }
+
+ bufferedReader.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ Log.i(TAG, "Number of building points " + buildingPoints.size());
+
+ /*
+ * inputStream = context.getResources().openRawResource(R.raw.buildings_shapes); bufferedReader = new BufferedReader(new
+ * InputStreamReader(inputStream));
+ *
+ * try { String def = bufferedReader.readLine(); // Log.i(TAG, "Reading the definition " + def);
+ *
+ * while ((strLine = bufferedReader.readLine()) != null) { // Log.i(TAG, "Data: " + strLine); String[] dataBits = strLine.split(","); Polygon poly =
+ * Util.csPolygonToPolygon(strLine.split("\"")[1]); // Log.i(TAG, "Creating building with id " + dataBits[0] + " and " + poly);
+ * buildingPolys.put(dataBits[0], poly); }
+ *
+ * bufferedReader.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
+ *
+ * Log.i(TAG, "Number of polys points " + buildingPolys.size());
+ */
+
+ inputStream = context.getAssets().open("building_estates.csv");
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+
+ try {
+ String def = bufferedReader.readLine();
+ // Log.i(TAG, "Reading the definition " + def);
+
+ while ((strLine = bufferedReader.readLine()) != null) {
+ // Log.i(TAG, "Data: " + strLine);
+ if (strLine.startsWith("\"")) {
+ String[] quoteBits = strLine.split("\"");
+ // Log.i(TAG, "QuoteBits " + quoteBits[0] + " | " + quoteBits[1]);
+ String[] dataBits = quoteBits[2].split(",");
+ // Log.i(TAG, "dataBits " + dataBits[0] + " | " + dataBits[1]);
+
+ if (buildingPoints.get(dataBits[1]) == null) {
+ // Log.w(TAG, "Building " + dataBits[1] + " has a null point");
+ continue;
+ }
+
+ Building bdg = new Building(dataBits[1], buildingPoints.get(dataBits[1]), dataBits[3].equals("R"), quoteBits[0]);
+ /*
+ * Polygon poly = buildingPolys.get(dataBits[1]);
+ *
+ * if (poly != null) { bdg.outline = poly; // Log.i(TAG, "Adding building " + key + " " + bdg.point.getLatitudeE6() + " " +
+ * bdg.point.getLongitudeE6() + " " + poly); } else { // Log.i(TAG, "Adding building " + key + " " + bdg.point.getLatitudeE6() + " " +
+ * bdg.point.getLongitudeE6()); }
+ */
+
+ // Log.i(TAG, "Creating building " + bdg.id + " " + bdg.name + " " + bdg.point + " " + bdg.residential + " " + bdg.outline);
+
+ buildingDao.create(bdg);
+
+ } else {
+
+ String[] dataBits = strLine.split(",");
+
+ if (buildingPoints.get(dataBits[1]) == null) {
+ // Log.w(TAG, "Building " + dataBits[1] + " has a null point");
+ continue;
+ }
+
+ Building bdg = new Building(dataBits[1], buildingPoints.get(dataBits[1]), dataBits[3].equals("R"), dataBits[0]);
+ /*
+ * Polygon poly = buildingPolys.get(dataBits[1]);
+ *
+ * if (poly != null) { bdg.outline = poly; // Log.i(TAG, "Adding building " + key + " " + bdg.point.getLatitudeE6() + " " +
+ * bdg.point.getLongitudeE6() + " " + poly); } else { // Log.i(TAG, "Adding building " + key + " " + bdg.point.getLatitudeE6() + " " +
+ * bdg.point.getLongitudeE6()); }
+ */
+
+ // Log.i(TAG, "Creating building " + bdg.id + " " + bdg.name + " " + bdg.point + " " + bdg.residential + " " + bdg.outline);
+
+ buildingDao.create(bdg);
+
+ }
+ }
+
+ bufferedReader.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ /*
+ * for (Iterator<String> iter = buildingPoints.keySet().iterator(); iter.hasNext();) { String key = iter.next();
+ *
+ * Building bdg = new Building(key, buildingPoints.get(key), false); Polygon poly = buildingPolys.get(key);
+ *
+ * if (poly != null) { bdg.outline = poly; // Log.i(TAG, "Adding building " + key + " " + bdg.point.getLatitudeE6() + " " + bdg.point.getLongitudeE6() +
+ * " " + poly); } else { // Log.i(TAG, "Adding building " + key + " " + bdg.point.getLatitudeE6() + " " + bdg.point.getLongitudeE6()); }
+ *
+ * buildingDao.create(bdg); }
+ */
+
+ }
+
+ public static void loadBusData(Context context, boolean onlyUniLink) throws SQLException, IOException {
+ DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+
+ Dao<BusStop, String> busStopDao = helper.getBusStopDao();
+ Dao<BusRoute, Integer> busRouteDao = helper.getBusRouteDao();
+ Dao<RouteStops, Integer> routeStopsDao = helper.getRouteStopsDao();
+
+ TableUtils.clearTable(helper.getConnectionSource(), BusStop.class);
+ TableUtils.clearTable(helper.getConnectionSource(), BusRoute.class);
+ TableUtils.clearTable(helper.getConnectionSource(), RouteStops.class);
+
+ Log.i(TAG, "Loading busstops from csv");
+
+ InputStream inputStream = context.getAssets().open("bus_stops.csv");
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ String strLine = "";
+
+ try {
+ String def = bufferedReader.readLine();
+ // Log.i(TAG, "Reading the definition " +def );
+
+ while ((strLine = bufferedReader.readLine()) != null) {
+ // Log.i(TAG, "Data: " + strLine);
+ String[] dataBits = strLine.split(",");
+
+ String[] quBitsLat = dataBits[3].substring(1, dataBits[3].length() - 1).split(" ");
+ String[] quBitsLng = dataBits[4].substring(1, dataBits[4].length() - 1).split(" ");
+
+ // Log.i(TAG, "Whole " + dataBits[3] + " First bit " + quBitsLat[0] + " last bit " + quBitsLat[1]);
+ double lat = Double.valueOf(quBitsLat[0]) + Double.valueOf(quBitsLat[1].substring(0, quBitsLat[1].length() - 1)) / 60d; // TODO Much hackage
+ // Log.i(TAG, "Whole " + dataBits[4] + " First bit " + quBitsLng[0] + " last bit " + quBitsLng[1]);
+ double lng = Double.valueOf(quBitsLng[0]) + Double.valueOf(quBitsLng[1].substring(0, quBitsLng[1].length() - 1)) / 60d; // TODO Much hackage
+ GeoPoint point = new GeoPoint((int) (lat * 1e6), (int) (lng * -1e6));
+ // Log.i(TAG, "Lat " + point.getLatitudeE6() + " lng " + point.getLongitudeE6());
+
+ busStopDao.create(new BusStop(dataBits[0].replace("\"", ""), dataBits[1].replace("\"", ""), dataBits[2].replace("\"", ""), point));
+
+ }
+
+ bufferedReader.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ Log.e(TAG, "Line: " + strLine);
+ e.printStackTrace();
+ }
+
+ Log.i(TAG, "Finished loading busstops, now loading routes");
+
+ inputStream = context.getAssets().open("routes.csv");
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+
+ try {
+ String def = bufferedReader.readLine();
+ // Log.i(TAG, "Reading the definition " + def);
+
+ while ((strLine = bufferedReader.readLine()) != null) {
+ // Log.i(TAG, "Data: " + strLine);
+ String[] dataBits = strLine.split(",");
+
+ BusRoute route = new BusRoute(Integer.parseInt(dataBits[0]), dataBits[1], dataBits[2].replace("\"", ""));
+ // Log.i(TAG, "Loaded route " + route.id + " " + route.code + " " + route.label);
+ busRouteDao.create(route);
+
+ }
+
+ bufferedReader.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ Log.e(TAG, "Line: " + strLine);
+ e.printStackTrace();
+ }
+
+ Log.i(TAG, "Finished loading routes, now loading routestops");
+
+ inputStream = context.getAssets().open("routestops.csv");
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+
+ try {
+ String def = bufferedReader.readLine();
+ // Log.i(TAG, "Reading the definition " + def);
+
+ while ((strLine = bufferedReader.readLine()) != null) {
+ // Log.i(TAG, "Data: " + strLine);
+ String[] dataBits = strLine.split(",");
+
+ BusStop stop = busStopDao.queryForId(dataBits[2]);
+ if (stop != null) {
+ // Log.i(TAG, "Found stop " + stop.id);
+ } else {
+ Log.w(TAG, "No stop found for " + dataBits[2]);
+ continue;
+ }
+
+ BusRoute route = busRouteDao.queryForId(Integer.parseInt(dataBits[0]));
+ if (route != null) {
+ // Log.i(TAG, "Found route " + route.id);
+ } else {
+ Log.w(TAG, "No route found for " + dataBits[0]);
+ continue;
+ }
+
+ int sequence = Integer.parseInt(dataBits[1]);
+ Log.i(TAG, "Creating RouteStop " + stop.id + " " + route.code + " " + sequence);
+
+ routeStopsDao.create(new RouteStops(stop, route, sequence));
+
+ if (route.id == 326) { // U1
+ stop.routes = (byte) (stop.routes | 1);
+ } else if (route.id == 468) { // U1N
+ stop.routes = (byte) (stop.routes | (1 << 1));
+ } else if (route.id == 329) { // U2
+ stop.routes = (byte) (stop.routes | (1 << 2));
+ } else if (route.id == 327) { // U6
+ stop.routes = (byte) (stop.routes | (1 << 3));
+ } else if (route.id == 354) { // U9
+ stop.routes = (byte) (stop.routes | (1 << 4));
+ }
+ Log.v(TAG, "Stop routes " + stop.routes);
+ busStopDao.update(stop);
+
+ }
+
+ bufferedReader.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ Log.e(TAG, "Line: " + strLine);
+ e.printStackTrace();
+ }
+
+ // TODO: Seperate non unilink stuff in to a different table
+ if (onlyUniLink) {
+
+ long sizeBeforeRemoval = busStopDao.countOf();
+
+ // Removing busstops not used by unilink busses
+ for (Iterator<BusStop> busStopIter = busStopDao.iterator(); busStopIter.hasNext();) {
+ BusStop stop = busStopIter.next();
+ // Log.i(TAG, "Looking at stop " + stop.id);
+
+ /*
+ * QueryBuilder<RouteStops, Integer> routeStopsQueryBuilder = routeStopsDao.queryBuilder(); routeStopsQueryBuilder.where().eq(columnName, value)
+ *
+ * DeleteBuilder<BusStop, String> deleteBuilder = busStopDao.deleteBuilder(); // only delete the rows where password is null
+ * deleteBuilder.where().in(RouteStops.STOP_ID_FIELD_NAME, objects) accountDao.delete(deleteBuilder.prepare());
+ */
+
+ QueryBuilder<RouteStops, Integer> routeStopsQueryBuilder = routeStopsDao.queryBuilder();
+ routeStopsQueryBuilder.setCountOf(true);
+ routeStopsQueryBuilder.where().eq(RouteStops.STOP_ID_FIELD_NAME, stop);
+
+ PreparedQuery<RouteStops> routeStopsPreparedQuery = routeStopsQueryBuilder.prepare();
+ long num = routeStopsDao.countOf(routeStopsPreparedQuery);
+ // long num = routeStopsDao.query(routeStopsPreparedQuery).size();
+ // Log.i(TAG, "Number is " + num);
+ if (num == 0) {
+ // Log.i(TAG, "Removing " + stop.id);
+ busStopIter.remove();
+ }
+ }
+
+ long sizeAfterRemoval = busStopDao.countOf();
+
+ Log.i(TAG, "Removed " + (sizeBeforeRemoval - sizeAfterRemoval) + " stops (from " + sizeBeforeRemoval + ") now have " + sizeAfterRemoval);
+
+ }
+
+ Log.i(TAG, "Finished loading bus data");
+ }
+
+ public static void loadSiteData(Context context) throws SQLException, IOException {
+ Log.i(TAG, "Begining loading site data");
+
+ DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+
+ TableUtils.clearTable(helper.getConnectionSource(), Site.class);
+
+ Dao<Site, String> siteDao = helper.getSiteDao();
+
+ InputStream inputStream = context.getAssets().open("sites.csv");
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ String strLine = null;
+
+ try {
+ String def = bufferedReader.readLine();
+ // Log.i(TAG, "Reading the site definition " + def);
+
+ while ((strLine = bufferedReader.readLine()) != null) {
+ // Log.i(TAG, "Site Data: " + strLine);
+ String[] dataBits = strLine.split(",");
+
+ GeoPoint point = null;
+ if (dataBits[2].length() > 1 && dataBits[3].length() > 1) {
+ point = Util.csLatLongToGeoPoint(dataBits[2], dataBits[3]);
+ } else {
+ point = new GeoPoint(0, 0);
+ }
+
+ Polygon poly = Util.csPolygonToPolygon(strLine.split("\"")[1]);
+ // Log.i(TAG, "Polygon: " + poly);
+
+ siteDao.create(new Site(dataBits[0], dataBits[1], point, poly));
+ }
+
+ bufferedReader.close();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ Log.e(TAG, "Site Line: " + strLine);
+ e.printStackTrace();
+ }
+
+ Log.i(TAG, "Loaded sites from csv");
+ }
+
+ private static Stop getStop(Context context, JSONObject stopObj, BusStop busStop) throws SQLException {
+
+ if (helper == null)
+ helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+ if (busRoutes == null)
+ busRoutes = helper.getBusRouteDao();
+ if (busDao == null)
+ busDao = helper.getBusDao();
+ if (busStopDao == null)
+ busStopDao = helper.getBusStopDao();
+ if (stopDao == null)
+ stopDao = helper.getStopDao();
+
+ // Log.i(TAG, "Stop " + stopObj);
+
+ try {
+ String time = stopObj.getString("time");
+
+ GregorianCalendar calender = new GregorianCalendar();
+
+ if (!time.equals("Due")) {
+
+ Log.i(TAG, "Time: " + time + " current time " + calender.getTime());
+
+ if (time.contains(":")) {
+ String[] minAndHour = time.split(":");
+ calender.set(Calendar.HOUR_OF_DAY, Integer.parseInt(minAndHour[0]));
+ calender.set(Calendar.MINUTE, Integer.parseInt(minAndHour[1]));
+ } else {
+ // Log.i(TAG, "Parsing " + time.substring(0, time.length() - 1) + " for min");
+ calender.add(Calendar.MINUTE, Integer.parseInt(time.substring(0, time.length() - 1)));
+ }
+
+ Log.i(TAG, "Date: " + calender.getTime());
+
+ }
+
+ Stop stop;
+
+ String name = stopObj.getString("name");
+
+ BusRoute route;
+
+ if (name.equals("U1N")) {
+ route = busRoutes.queryForId(468);
+ } else if (name.startsWith("U1")) {
+ route = busRoutes.queryForId(326);
+ } else if (name.startsWith("U2")) {
+ route = busRoutes.queryForId(329);
+ } else if (name.startsWith("U6")) {
+ route = busRoutes.queryForId(327);
+ } else if (name.startsWith("U9")) {
+ route = busRoutes.queryForId(354);
+ } else {
+ Log.e(TAG, "Error selecting route for " + name);
+ return null;
+ }
+
+ String destString = stopObj.getString("dest");
+ BusStop destStop;
+
+ if (destString.equals("Central Station")) {
+ destStop = busStopDao.queryForId("SNA19709");
+ } else if (destString.equals("Civic Centre")) {
+ destStop = busStopDao.queryForId("SN120527");
+ } else if (destString.equals("City DG4")) {
+ destStop = busStopDao.queryForId("HAA13579");
+ } else if (destString.equals("Central Station")) {
+ destStop = busStopDao.queryForId("SN120520");
+ } else if (destString.equals("Airport")) {
+ destStop = busStopDao.queryForId("HA030184");
+ } else if (destString.equals("City, Town Quay")) {
+ destStop = busStopDao.queryForId("SNA13766");
+ } else if (destString.equals("Dock Gate 4")) {
+ destStop = busStopDao.queryForId("MG1031");
+ } else if (destString.equals("Eastleigh")) {
+ destStop = busStopDao.queryForId("HA030212");
+ } else if (destString.equals("Crematorium")) {
+ destStop = busStopDao.queryForId("SN121009");
+ } else if (destString.equals("General Hosp")) {
+ destStop = busStopDao.queryForId("SNA19482");
+ } else {
+ Log.e(TAG, "Unknown end dest " + destString + " for route " + route.code);
+ return null;
+ }
+
+ if (stopObj.has("vehicle")) {
+
+ int vehicle = Integer.parseInt(stopObj.getString("vehicle"));
+ // Log.i(TAG, "Looking at vehicle " + vehicle + " (" + stopObj.getString("vehicle") + ")");
+ Bus bus = busDao.queryForId(vehicle);
+ if (bus == null) {
+ // Log.i(TAG, "Cant find vehicle, creating");
+
+ // for (Bus gotBus : busDao) {
+ // Log.i(TAG, "Currently have bus " + gotBus.id);
+ // }
+
+ bus = new Bus(vehicle, route);
+ busDao.create(bus);
+ }
+
+ Date now = new Date(System.currentTimeMillis());
+
+ stop = new Stop(stopObj.getString("name"), busStop, destStop, bus, calender.getTime(), now);
+
+ /*
+ * if (bus.lastKnownStop != null) { stopDao.delete(bus.lastKnownStop); // TODO Crude, might delete useful data
+ *
+ * if (bus.lastKnownStop.arivalTime == null) { Log.e(TAG, " bus.lastKnownStop.arivalTime is null"); } else if (stop.arivalTime == null) {
+ * Log.e(TAG, " stop.arivalTime is null"); }
+ *
+ * if (bus.lastKnownStop.arivalTime.before(stop.arivalTime) && bus.lastKnownStop.arivalTime.after(now)) { bus.lastKnownStop = stop;
+ *
+ * if (bus.firstKnownStop == null) { bus.firstKnownStop = stop;
+ *
+ * } else if (!bus.firstKnownStop.busStop.equals(stop.busStop)) { stopDao.delete(bus.firstKnownStop); // TODO Crude, might delete useful data
+ *
+ * bus.firstKnownStop = stop; }
+ *
+ * } }
+ */
+
+ // busDao.update(bus);
+
+ } else {
+
+ stop = new Stop(stopObj.getString("name"), busStop, destStop, calender.getTime(), new Date(System.currentTimeMillis()));
+
+ }
+
+ return stop;
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ Log.e(TAG, "Error parsing stop " + stopObj, e);
+ return null;
+ }
+
+ }
+
+ public static boolean updateStop(BusStop busStop, boolean onlyUniLink) {
+ String file = getFileFromServer(busStopUrl + busStop.id + ".json");
+
+ try {
+ JSONObject data = new JSONObject(file);
+
+ JSONArray stopsArray = data.getJSONArray("stops");
+
+ // Log.i(TAG, "Number of entries " + data.length());
+
+ // Log.i(TAG, "Stops: " + data.getJSONArray("stops"));
+
+ for (int stopNum = 0; stopNum < stopsArray.length(); stopNum++) {
+ JSONObject stopObj = stopsArray.getJSONObject(stopNum);
+
+ if (onlyUniLink && !stopObj.getString("name").startsWith("U")) {
+ continue;
+ }
+
+ Stop stop = getStop(context, stopObj, busStop);
+
+ if (stop == null) {
+ Log.w(TAG, "Null stop, skiping");
+ continue;
+ }
+
+ if (stop.bus != null) {
+ Log.i(TAG, "Found stop for " + stop.bus.id + " at " + stop.busStop.id + " at " + stop.arivalTime);
+ } else {
+ if (stop.name == null) {
+ Log.e(TAG, "Null name");
+ } else if (stop.busStop == null) {
+ Log.e(TAG, "Null busStop");
+ } else if (stop.arivalTime == null) {
+ Log.e(TAG, "Null arivalTime");
+ }
+ Log.i(TAG, "Found stop for a unidentified " + stop.name + " at " + stop.busStop.id + " at " + stop.arivalTime);
+ }
+
+ // stopDao.create(stop);
+ }
+ } catch (JSONException ex) {
+ Log.e(TAG, "", ex);
+
+ return false;
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+
+ return false;
+ }
+
+ return false;
+
+ }
+
+ public static Timetable getTimetable(Context context, String busStop, boolean onlyUniLink) throws SQLException {
+
+ if (helper == null)
+ helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+ if (busRoutes == null)
+ busRoutes = helper.getBusRouteDao();
+ if (stopDao == null)
+ stopDao = helper.getStopDao();
+ if (busStopDao == null)
+ busStopDao = helper.getBusStopDao();
+
+ Timetable timetable = new Timetable();
+
+ String file = getFileFromServer(busStopUrl + busStop + ".json");
+
+ try {
+ JSONObject data = new JSONObject(file);
+
+ JSONArray stopsArray = data.getJSONArray("stops");
+
+ Log.i(TAG, "Number of entries " + data.length());
+
+ Log.i(TAG, "Stops: " + data.getJSONArray("stops"));
+
+ for (int stopNum = 0; stopNum < stopsArray.length(); stopNum++) {
+ JSONObject stopObj = stopsArray.getJSONObject(stopNum);
+
+ if (onlyUniLink && !stopObj.getString("name").startsWith("U")) {
+ continue;
+ }
+
+ BusStop busStopObj = busStopDao.queryForId(busStop);
+ if (busStopObj == null) {
+ Log.e(TAG, "BusStopObj == null");
+ }
+
+ Stop stop = getStop(context, stopObj, busStopObj);
+
+ if (stop == null) {
+ Log.w(TAG, "Null stop, skiping");
+ continue;
+ }
+
+ if (stop.bus != null) {
+ Log.i(TAG, "Found stop for " + stop.bus.id + " at " + stop.busStop.id + " at " + stop.arivalTime);
+ } else {
+ Log.i(TAG, "Found stop for a unidentified " + stop.name + " at " + stop.busStop.id + " at " + stop.arivalTime);
+ }
+
+ timetable.add(stop);
+ }
+ } catch (JSONException ex) {
+ Log.e(TAG, "", ex);
+ Log.e(TAG, "File: " + file);
+ return null;
+ }
+
+ return timetable;
+ }
+
+ static PathOverlay getRoutePath(InputStream routeResource, int colour, ResourceProxy resProxy) {
+ PathOverlay data = null;
+
+ // sax stuff
+ try {
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ SAXParser sp = spf.newSAXParser();
+
+ XMLReader xr = sp.getXMLReader();
+
+ DataHandler dataHandler = new DataHandler(colour, resProxy);
+ xr.setContentHandler(dataHandler);
+
+ xr.parse(new InputSource(routeResource));
+
+ data = dataHandler.getData();
+
+ } catch (ParserConfigurationException pce) {
+ Log.e("SAX XML", "sax parse error", pce);
+ } catch (SAXException se) {
+ Log.e("SAX XML", "sax error", se);
+ } catch (IOException ioe) {
+ Log.e("SAX XML", "sax parse io error", ioe);
+ }
+
+ return data;
+ }
+
+ public static String getFileFromServer(String request) {
+ StringBuilder builder = new StringBuilder();
+ HttpClient client = new DefaultHttpClient();
+ HttpGet httpGet = new HttpGet(request);
+ Log.i("Util.getFileFromServer", "Request used: " + request);
+ try {
+ HttpResponse response = client.execute(httpGet);
+ StatusLine statusLine = response.getStatusLine();
+ int statusCode = statusLine.getStatusCode();
+ if (statusCode == 200) {
+ HttpEntity entity = response.getEntity();
+ InputStream content = entity.getContent();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(content));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ builder.append(line);
+ }
+ } else {
+ Log.e("", "Failed to download file");
+ }
+ } catch (Exception ex) {
+ Log.e("Util.getFileFromServer", ex.getClass().toString() + " " + ex.getMessage());
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/src/net/cbaines/suma/DatabaseHelper.java b/src/net/cbaines/suma/DatabaseHelper.java
new file mode 100644
index 0000000..28ad6a5
--- /dev/null
+++ b/src/net/cbaines/suma/DatabaseHelper.java
@@ -0,0 +1,279 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.sql.SQLException;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.util.Log;
+
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.TableUtils;
+
+public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
+
+ private static final String DATABASE_PATH = "/data/data/net.cbaines.suma/databases/";
+ private static final String DATABASE_NAME = "data.db";
+
+ private static final int DATABASE_VERSION = 36;
+
+ private static final String TAG = "DatabaseHelper";
+
+ // the DAO object we use to access the SimpleData table
+ private Dao<Building, String> buildingDao = null;
+ private Dao<BusStop, String> busStopDao = null;
+ private Dao<BusRoute, Integer> busRouteDao = null;
+ private Dao<RouteStops, Integer> routeStopsDao = null;
+ private Dao<Site, String> siteDao = null;
+ private Dao<Bus, Integer> busDao = null;
+ private Dao<Stop, Integer> stopDao = null;
+
+ private Context context;
+
+ public DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ Log.i(TAG, "Database Helper created");
+ this.context = context;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
+ try {
+ Log.i(DatabaseHelper.class.getName(), "onCreate");
+ TableUtils.createTable(connectionSource, Building.class);
+ TableUtils.createTable(connectionSource, BusStop.class);
+ TableUtils.createTable(connectionSource, BusRoute.class);
+ TableUtils.createTable(connectionSource, RouteStops.class);
+ TableUtils.createTable(connectionSource, Site.class);
+ TableUtils.createTable(connectionSource, Bus.class);
+ TableUtils.createTable(connectionSource, Stop.class);
+ } catch (SQLException e) {
+ Log.e(DatabaseHelper.class.getName(), "Can't create database", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
+ try {
+ Log.i(DatabaseHelper.class.getName(), "onUpgrade");
+ TableUtils.dropTable(connectionSource, Building.class, true);
+ TableUtils.dropTable(connectionSource, BusStop.class, true);
+ TableUtils.dropTable(connectionSource, BusRoute.class, true);
+ TableUtils.dropTable(connectionSource, RouteStops.class, true);
+ TableUtils.dropTable(connectionSource, Site.class, true);
+ TableUtils.dropTable(connectionSource, Bus.class, true);
+ TableUtils.dropTable(connectionSource, Stop.class, true);
+ // after we drop the old databases, we create the new ones
+ onCreate(database, connectionSource);
+ } catch (SQLException e) {
+ Log.e(DatabaseHelper.class.getName(), "Can't drop databases", e);
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ /**
+ * Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached value.
+ */
+ public Dao<Building, String> getBuildingDao() throws SQLException {
+ if (buildingDao == null) {
+ buildingDao = getDao(Building.class);
+ }
+ return buildingDao;
+ }
+
+ /**
+ * Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached value.
+ */
+ public Dao<BusStop, String> getBusStopDao() throws SQLException {
+ if (busStopDao == null) {
+ busStopDao = getDao(BusStop.class);
+ }
+ return busStopDao;
+ }
+
+ /**
+ * Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached value.
+ */
+ public Dao<BusRoute, Integer> getBusRouteDao() throws SQLException {
+ if (busRouteDao == null) {
+ busRouteDao = getDao(BusRoute.class);
+ }
+ return busRouteDao;
+ }
+
+ /**
+ * Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached value.
+ */
+ public Dao<RouteStops, Integer> getRouteStopsDao() throws SQLException {
+ if (routeStopsDao == null) {
+ routeStopsDao = getDao(RouteStops.class);
+ }
+ return routeStopsDao;
+ }
+
+ /**
+ * Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached value.
+ */
+ public Dao<Site, String> getSiteDao() throws SQLException {
+ if (siteDao == null) {
+ siteDao = getDao(Site.class);
+ }
+ return siteDao;
+ }
+
+ /**
+ * Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached value.
+ */
+ public Dao<Bus, Integer> getBusDao() throws SQLException {
+ if (busDao == null) {
+ busDao = getDao(Bus.class);
+ }
+ return busDao;
+ }
+
+ /**
+ * Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached value.
+ */
+ public Dao<Stop, Integer> getStopDao() throws SQLException {
+ if (stopDao == null) {
+ stopDao = getDao(Stop.class);
+ }
+ return stopDao;
+ }
+
+ /**
+ * Check if the database already exist to avoid re-copying the file each time you open the application.
+ *
+ * @return true if it exists, false if it doesn't
+ */
+ public boolean checkDataBase() {
+ Log.i(TAG, "Check database");
+
+ SQLiteDatabase checkDB = null;
+
+ try {
+ String myPath = DATABASE_PATH + DATABASE_NAME;
+ checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
+ } catch (SQLiteException e) {
+
+ // database does't exist yet.
+
+ }
+
+ if (checkDB != null) {
+
+ checkDB.close();
+
+ }
+
+ Log.i(TAG, "Finished checking database");
+ return checkDB != null ? true : false;
+ }
+
+ /**
+ * Copies your database from your local assets-folder to the just created empty database in the system folder, from where it can be accessed and handled.
+ * This is done by transfering bytestream.
+ * */
+ public void copyDataBase() throws IOException {
+ Log.i(TAG, "Begining copy database");
+
+ // By calling this method and empty database will be created into the default system path
+ // of your application so we are gonna be able to overwrite that database with our database.
+ Log.i(TAG, "GetReadableDatabase");
+ this.getWritableDatabase().close();
+
+ InputStream myInput = context.getAssets().open(DATABASE_NAME);
+
+ // Path to the just created empty db
+ String outFileName = DATABASE_PATH + DATABASE_NAME;
+
+ File database = new File(outFileName);
+ if (database.exists()) {
+ database.delete();
+ }
+
+ // Open the empty db as the output stream
+ OutputStream myOutput = new FileOutputStream(outFileName);
+
+ // transfer bytes from the inputfile to the outputfile
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = myInput.read(buffer)) > 0) {
+ myOutput.write(buffer, 0, length);
+ }
+
+ // Close the streams
+ myOutput.flush();
+ myOutput.close();
+ myInput.close();
+
+ // getWritableDatabase().close();
+
+ Log.i(TAG, "Finished copying db");
+
+ }
+
+ /**
+ * Creates a empty database on the system and rewrites it with your own database.
+ * */
+ public void createDataBase() throws IOException {
+
+ boolean dbExist = checkDataBase();
+
+ if (dbExist) {
+ // do nothing - database already exist
+ } else {
+
+ try {
+ Log.i(TAG, "Copy database");
+ copyDataBase();
+ } catch (IOException e) {
+ throw new Error("Error copying database");
+ }
+ }
+
+ }
+
+ /**
+ * Close the database connections and clear any cached DAOs.
+ */
+ @Override
+ public void close() {
+ super.close();
+ buildingDao = null;
+ busStopDao = null;
+ busRouteDao = null;
+ routeStopsDao = null;
+ siteDao = null;
+ busDao = null;
+ stopDao = null;
+ }
+} \ No newline at end of file
diff --git a/src/net/cbaines/suma/DonateDialog.java b/src/net/cbaines/suma/DonateDialog.java
new file mode 100644
index 0000000..0c0c45f
--- /dev/null
+++ b/src/net/cbaines/suma/DonateDialog.java
@@ -0,0 +1,92 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import android.app.Dialog;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+public class DonateDialog extends Dialog implements Runnable {
+
+ // private static final String TAG = "DonateDialog";
+
+ private static final String bitcoinAddress = "1LFATViKkmbm6m4u1Ghi9wqrgVy2B6M412";
+
+ private final Context context;
+
+ private final TextView dialogMessage;
+ private final ProgressBar progressBar;
+
+ private final LinearLayout errorLayout;
+ private final TextView donateDialogErrorMessage;
+ private final TextView donateBitcoinAddress;
+
+ public DonateDialog(Context context) {
+ super(context);
+
+ this.context = context;
+
+ setContentView(R.layout.donate_dialog);
+ setTitle("Donate");
+
+ dialogMessage = (TextView) findViewById(R.id.donateDialogMessage);
+ progressBar = (ProgressBar) findViewById(R.id.donateDialogProgress);
+
+ errorLayout = (LinearLayout) findViewById(R.id.donateDialogMessageLayout);
+ donateDialogErrorMessage = (TextView) findViewById(R.id.donateDialogErrorMessage);
+ donateBitcoinAddress = (TextView) findViewById(R.id.donateBitcoinAddress);
+
+ new Thread(this).start();
+ }
+
+ public void run() {
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ try {
+
+ Intent donateIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("bitcoin:?" + bitcoinAddress
+ + "&label=Southampton%20Uni%20Map%20App&message=Donation%20for%20the%20Southampton%20University%20Map%20App"));
+ context.startActivity(donateIntent);
+
+ } catch (ActivityNotFoundException e) {
+ errorLayout.post(new Runnable() {
+ public void run() {
+ dialogMessage.setText(R.string.donate_dialog_error_title);
+ progressBar.setVisibility(View.GONE);
+ errorLayout.setVisibility(View.VISIBLE);
+ donateDialogErrorMessage.setVisibility(View.VISIBLE);
+ donateBitcoinAddress.setText(bitcoinAddress);
+ donateBitcoinAddress.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+ }
+
+}
diff --git a/src/net/cbaines/suma/FavouriteDialog.java b/src/net/cbaines/suma/FavouriteDialog.java
new file mode 100644
index 0000000..dfd5690
--- /dev/null
+++ b/src/net/cbaines/suma/FavouriteDialog.java
@@ -0,0 +1,130 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.j256.ormlite.android.apptools.OpenHelperManager;
+import com.j256.ormlite.dao.Dao;
+
+public class FavouriteDialog extends Dialog {
+
+ private static final String TAG = "FavouriteDialog";
+ private ListView listItems;
+
+ private final Context context;
+
+ private final TextView message;
+
+ protected POIArrayAdapter adapter;
+
+ private ArrayList<POI> favouriteItems;
+
+ public FavouriteDialog(Context context) {
+ super(context);
+
+ this.context = context;
+
+ setContentView(R.layout.favourite_dialog);
+ setTitle("Favourite Items");
+
+ message = (TextView) findViewById(R.id.favouriteDialogMessage);
+
+ favouriteItems = new ArrayList<POI>();
+
+ listItems = (ListView) findViewById(R.id.favouriteListItems);
+ }
+
+ public void refresh() {
+
+ DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+
+ try {
+
+ Dao<Building, String> buildingDao = helper.getBuildingDao();
+ Dao<BusStop, String> busStopDao = helper.getBusStopDao();
+
+ final ArrayList<POI> newFavouriteItems = new ArrayList<POI>();
+
+ newFavouriteItems.addAll(buildingDao.queryForEq(POI.FAVOURITE_FIELD_NAME, true));
+ newFavouriteItems.addAll(busStopDao.queryForEq(POI.FAVOURITE_FIELD_NAME, true));
+
+ Log.i(TAG, "There are " + newFavouriteItems.size() + " favourites");
+ if (newFavouriteItems.size() == 0) {
+ Log.i(TAG, "Favourite dialog has no favourites, displaying message");
+ message.post(new Runnable() {
+ public void run() {
+ message.setText("No Favourite's, to make some buildings or bus stops favourite, just tap and hold them on the map");
+ message.setVisibility(View.VISIBLE);
+ }
+ });
+ listItems.post(new Runnable() {
+ public void run() {
+ listItems.setVisibility(View.GONE);
+ adapter = null;
+ favouriteItems.clear();
+ }
+ });
+
+ } else {
+ message.post(new Runnable() {
+ public void run() {
+ message.setVisibility(View.GONE);
+ }
+ });
+
+ listItems.post(new Runnable() {
+ public void run() {
+ favouriteItems = newFavouriteItems;
+ adapter = new POIArrayAdapter(context, favouriteItems);
+
+ listItems.setVisibility(View.VISIBLE);
+ listItems.setAdapter(adapter);
+
+ }
+ });
+
+ }
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ void setOnItemClickListener(OnItemClickListener item) {
+ listItems.setOnItemClickListener(item);
+
+ }
+
+ void setOnItemLongClickListener(OnItemLongClickListener item) {
+ listItems.setOnItemLongClickListener(item);
+ }
+
+}
diff --git a/src/net/cbaines/suma/FindActivity.java b/src/net/cbaines/suma/FindActivity.java
new file mode 100644
index 0000000..dbbff49
--- /dev/null
+++ b/src/net/cbaines/suma/FindActivity.java
@@ -0,0 +1,399 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.osmdroid.util.GeoPoint;
+
+import android.content.Context;
+import android.content.Intent;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+
+import com.j256.ormlite.android.apptools.OrmLiteBaseActivity;
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.stmt.PreparedQuery;
+import com.j256.ormlite.stmt.QueryBuilder;
+
+public class FindActivity extends OrmLiteBaseActivity<DatabaseHelper> implements Runnable, TextWatcher, OnItemClickListener, LocationListener,
+ OnItemLongClickListener {
+
+ final static String TAG = "FindActivity";
+
+ private EditText searchBar;
+ private ListView listItems;
+ private ProgressBar progBar;
+ private LinearLayout findContentLayout;
+
+ private String searchTerm = "";
+
+ private Dao<Building, String> buildingDao;
+ private Dao<BusStop, String> busStopDao;
+ private Dao<Site, String> siteDao;
+
+ private POIArrayAdapter adapter;
+ // private ArrayList<POI> POIsFound = new ArrayList<POI>();
+
+ private boolean dataChanged;
+
+ private GeoPoint userLocation;
+
+ private Thread searchThread;
+
+ ArrayList<POI> getNearestPOIs(int distance) {
+ Log.i(TAG, "Getting nearest POI's");
+ ArrayList<POI> nearestPOIs = new ArrayList<POI>();
+ for (Iterator<Building> buildingDaoIter = buildingDao.iterator(); buildingDaoIter.hasNext();) {
+ POI poi = buildingDaoIter.next();
+ int dist = poi.point.distanceTo(userLocation);
+ if (dist < distance) {
+ poi.distTo = dist;
+ nearestPOIs.add(poi);
+ }
+ }
+
+ for (Iterator<BusStop> busStopDaoIter = busStopDao.iterator(); busStopDaoIter.hasNext();) {
+ POI poi = busStopDaoIter.next();
+ int dist = poi.point.distanceTo(userLocation);
+ if (dist < distance) {
+ poi.distTo = dist;
+ nearestPOIs.add(poi);
+ }
+ }
+
+ Collections.sort(nearestPOIs, new POIDistanceComparator(userLocation, true));
+
+ Log.i(TAG, "Got " + nearestPOIs.size() + " nearest POI's");
+ return nearestPOIs;
+ }
+
+ // Search thread
+ public void run() {
+ POIArrayAdapter tempAdaptor;
+ GeoPoint thisUserLocation = userLocation;
+
+ Log.i(TAG, "Search thread started");
+ String thisSearchTerm = searchTerm;
+
+ ArrayList<POI> foundPOIsArray = null;
+
+ Log.i(TAG, "Search term length " + thisSearchTerm.length() + " userLocation == null " + (thisUserLocation == null));
+ if (thisSearchTerm.length() == 0 && thisUserLocation != null) {
+ foundPOIsArray = getNearestPOIs(200);
+
+ }
+
+ if (foundPOIsArray != null && foundPOIsArray.size() != 0) {
+
+ tempAdaptor = new POIArrayAdapter(this, foundPOIsArray);
+ } else {
+
+ try {
+
+ foundPOIsArray = new ArrayList<POI>();
+
+ if (thisSearchTerm.length() == 0) {
+ for (Building building : buildingDao) {
+ foundPOIsArray.add(building);
+ }
+
+ if (!thisSearchTerm.equals(searchTerm))
+ return;
+
+ for (BusStop busStop : busStopDao) {
+ foundPOIsArray.add(busStop);
+ }
+
+ if (!thisSearchTerm.equals(searchTerm))
+ return;
+
+ for (Site site : siteDao) {
+ foundPOIsArray.add(site);
+ }
+
+ } else {
+
+ QueryBuilder<Building, String> buildingQueryBuilder = buildingDao.queryBuilder();
+ buildingQueryBuilder.where().like(Building.ID_FIELD_NAME, "%" + thisSearchTerm + "%").or()
+ .like(Building.NAME_FIELD_NAME, "%" + thisSearchTerm + "%");
+ PreparedQuery<Building> buildingPreparedQuery = buildingQueryBuilder.prepare();
+ List<Building> buildings = buildingDao.query(buildingPreparedQuery);
+ for (Building building : buildings) {
+ foundPOIsArray.add(building);
+ }
+ buildings = null;
+
+ if (!thisSearchTerm.equals(searchTerm))
+ return;
+
+ if (thisSearchTerm.contains("site")) {
+ for (Site site : siteDao) {
+ foundPOIsArray.add(site);
+ }
+ } else {
+ QueryBuilder<Site, String> siteQueryBuilder = siteDao.queryBuilder();
+ siteQueryBuilder.where().like(Site.ID_FIELD_NAME, "%" + thisSearchTerm + "%").or()
+ .like(Site.NAME_FIELD_NAME, "%" + thisSearchTerm + "%");
+ PreparedQuery<Site> sitePreparedQuery = siteQueryBuilder.prepare();
+ List<Site> sites = siteDao.query(sitePreparedQuery);
+ for (Site site : sites) {
+ foundPOIsArray.add(site);
+ }
+ sites = null;
+ }
+
+ if (!thisSearchTerm.equals(searchTerm))
+ return;
+
+ // if (thisSearchTerm.contains("bus")) {
+ // for (BusStop busStop : busStopDao) {
+ // foundPOIsArray.add(busStop);
+ // }
+ // } else {
+ QueryBuilder<BusStop, String> busStopQueryBuilder = busStopDao.queryBuilder();
+ busStopQueryBuilder.where().like(BusStop.ID_FIELD_NAME, "%" + thisSearchTerm + "%").or()
+ .like(BusStop.DESCRIPTION_FIELD_NAME, "%" + thisSearchTerm + "%");
+ PreparedQuery<BusStop> busStopPreparedQuery = busStopQueryBuilder.prepare();
+ List<BusStop> busStops = busStopDao.query(busStopPreparedQuery);
+ for (BusStop busStop : busStops) {
+ foundPOIsArray.add(busStop);
+ }
+ busStops = null;
+ // }
+
+ if (!thisSearchTerm.equals(searchTerm))
+ return;
+
+ Log.i(TAG, "Found " + foundPOIsArray.size() + " pois");
+
+ if (thisUserLocation != null) {
+ Collections.sort(foundPOIsArray, new POIDistanceComparator(userLocation));
+ } else {
+ Collections.sort(foundPOIsArray, new StringDistanceComparator(thisSearchTerm));
+ }
+
+ }
+
+ if (!thisSearchTerm.equals(searchTerm))
+ return;
+
+ tempAdaptor = new POIArrayAdapter(this, foundPOIsArray);
+
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return;
+ }
+ }
+
+ if (thisSearchTerm.equals(searchTerm)) {
+ Log.i(TAG, "Search terms still equal, starting post");
+ adapter = tempAdaptor;
+ listItems.post(new Runnable() {
+ public void run() {
+ listItems.setAdapter(adapter);
+ if (progBar.getVisibility() != View.GONE) {
+ progBar.setVisibility(View.GONE);
+ findContentLayout.setGravity(Gravity.TOP);
+ }
+ }
+ });
+ } else {
+ Log.i(TAG, "Search terms no longer equal, exiting");
+ }
+ }
+
+ /** Called when the activity is first created. */
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.find);
+
+ searchBar = (EditText) findViewById(R.id.searchBar);
+ searchBar.addTextChangedListener(this);
+
+ listItems = (ListView) findViewById(R.id.findListItems);
+ listItems.setOnItemClickListener(this);
+ listItems.setOnItemLongClickListener(this);
+
+ progBar = (ProgressBar) findViewById(R.id.findLoadBar);
+ findContentLayout = (LinearLayout) findViewById(R.id.findContentLayout);
+
+ try {
+ buildingDao = getHelper().getBuildingDao();
+ busStopDao = getHelper().getBusStopDao();
+ siteDao = getHelper().getSiteDao();
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ // Acquire a reference to the system Location Manager
+ LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+ Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ if (lastKnownLocation != null) {
+ userLocation = Util.locationToGeoPoint(lastKnownLocation);
+ } else {
+ lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
+ if (lastKnownLocation != null) {
+ userLocation = Util.locationToGeoPoint(lastKnownLocation);
+
+ }
+ }
+ // Register the listener with the Location Manager to receive location updates
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10, this);
+ locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 10, this);
+
+ // SotonBusData.getTimetable("SN120128");
+
+ // Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("bitcoin:1F8fHWmWhqUJGhXUvY57mUof41wMUaeKH7?amount=1X8&label=SUC"));
+ // startActivity(browserIntent);
+ // 1F8fHWmWhqUJGhXUvY57mUof41wMUaeKH7
+
+ searchThread = new Thread(this);
+ searchThread.start();
+
+ }
+
+ public void afterTextChanged(Editable s) {
+ searchTerm = s.toString();
+ Log.i(TAG, "Text changed " + searchTerm + " starting search thread");
+ new Thread(this).start();
+ }
+
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Log.i(TAG, "OnItemClick pos " + position + " id " + id);
+
+ String poiId = adapter.getItemStringId(position);
+
+ Log.i(TAG, "POI " + poiId + " selected");
+
+ // Intent i = new Intent(FindActivity.this, SouthamptonUniversityMapActivity.class);
+ getIntent().putExtra("poi", poiId);
+ // startActivity(i);
+
+ setResult(RESULT_OK, getIntent());
+ finish();
+ }
+
+ public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+
+ POI poi = adapter.getPOIItem(position);
+
+ Log.i(TAG, "Long Click Event ID: " + poi.id);
+
+ if (poi.type.equals(POI.BUS_STOP)) {
+ Log.i(TAG, "Its a bus stop");
+
+ BusStop busStop = (BusStop) poi;
+
+ Intent i = new Intent(FindActivity.this, BusTimeActivity.class);
+ i.putExtra("busStopID", busStop.id);
+ i.putExtra("busStopName", busStop.description);
+ startActivityForResult(i, 0);
+ }
+
+ return false;
+ }
+
+ public void finish() {
+ getIntent().putExtra("dataChanged", dataChanged);
+ // startActivity(i);
+
+ setResult(RESULT_OK, getIntent());
+
+ super.finish();
+ }
+
+ public void onLocationChanged(Location location) {
+ Log.i(TAG, "Got location update for FindActivity");
+ userLocation = Util.locationToGeoPoint(location);
+ if (!searchThread.isAlive()) {
+ searchThread = new Thread(this);
+ searchThread.start();
+ }
+ }
+
+ public void onProviderDisabled(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void onProviderEnabled(String provider) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ // TODO Auto-generated method stub
+
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ Log.i(TAG, "Got activity result");
+ if (resultCode == RESULT_OK) {
+ // A contact was picked. Here we will just display it
+ // to the user.
+
+ boolean dataChangedInBusTimeActivity = false;
+
+ Bundle bundle = data.getExtras();
+ if (bundle == null) {
+ Log.i(TAG, "Bundle is null");
+ } else {
+ dataChangedInBusTimeActivity = bundle.getBoolean("dataChanged");
+ }
+
+ if (dataChangedInBusTimeActivity == true) {
+ dataChanged = true;
+ }
+
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/net/cbaines/suma/POI.java b/src/net/cbaines/suma/POI.java
new file mode 100644
index 0000000..37d6aaf
--- /dev/null
+++ b/src/net/cbaines/suma/POI.java
@@ -0,0 +1,94 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import org.osmdroid.util.GeoPoint;
+
+import com.j256.ormlite.field.DataType;
+import com.j256.ormlite.field.DatabaseField;
+
+public abstract class POI {
+ public static final String BUS_STOP = "busstop";
+ public static final String BUILDING = "building";
+ public static final String WAYPOINT = "waypoint";
+ public static final String SITE = "site";
+
+ public static final String ID_FIELD_NAME = "id";
+ public static final String POINT_FIELD_NAME = "point";
+ public static final String FAVOURITE_FIELD_NAME = "favourite";
+
+ POI() {
+ }
+
+ public POI(String id, GeoPoint point) {
+ this.id = id;
+ this.point = point;
+ }
+
+ @DatabaseField(dataType = DataType.SERIALIZABLE, canBeNull = false)
+ public GeoPoint point;
+
+ @DatabaseField(id = true)
+ public String id;
+
+ @DatabaseField(canBeNull = false)
+ public boolean favourite; // This field is not assessed by equals
+
+ int distTo = -1; // Used by the comparator to store distances, then later by the gui to display them.
+
+ public String type;
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((point == null) ? 0 : point.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ POI other = (POI) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (point == null) {
+ if (other.point != null)
+ return false;
+ } else if (!point.equals(other.point))
+ return false;
+ if (type == null) {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ return true;
+ }
+}
diff --git a/src/net/cbaines/suma/POIArrayAdapter.java b/src/net/cbaines/suma/POIArrayAdapter.java
new file mode 100644
index 0000000..83ee517
--- /dev/null
+++ b/src/net/cbaines/suma/POIArrayAdapter.java
@@ -0,0 +1,78 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.util.List;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+public class POIArrayAdapter extends BaseAdapter {
+
+ private final Context context;
+ private final List<POI> POIs;
+
+ public POIArrayAdapter(Context context, List<POI> pois) {
+ this.context = context;
+ this.POIs = pois;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ POIView poiView;
+ if (convertView == null) {
+ if (POIs.get(position).distTo == -1) {
+ poiView = new POIView(context, POIs.get(position));
+ } else {
+ poiView = new POIView(context, POIs.get(position), POIs.get(position).distTo);
+ }
+ } else {
+ poiView = (POIView) convertView;
+ if (POIs.get(position).distTo == -1) {
+ poiView = new POIView(context, POIs.get(position));
+ } else {
+ poiView = new POIView(context, POIs.get(position), POIs.get(position).distTo);
+ }
+ }
+
+ return poiView;
+ }
+
+ public int getCount() {
+ return POIs.size();
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public POI getPOIItem(int position) {
+ return POIs.get(position);
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public String getItemStringId(int position) {
+ return POIs.get(position).id;
+ }
+} \ No newline at end of file
diff --git a/src/net/cbaines/suma/POIDistanceComparator.java b/src/net/cbaines/suma/POIDistanceComparator.java
new file mode 100644
index 0000000..ef35112
--- /dev/null
+++ b/src/net/cbaines/suma/POIDistanceComparator.java
@@ -0,0 +1,50 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.util.Comparator;
+
+import org.osmdroid.util.GeoPoint;
+
+public class POIDistanceComparator implements Comparator<POI> {
+ private final GeoPoint userLocation;
+ private final boolean useExistingData;
+
+ public POIDistanceComparator(GeoPoint userLocation) {
+ this(userLocation, false);
+ }
+
+ public POIDistanceComparator(GeoPoint userLocation, boolean useData) {
+ super();
+ this.userLocation = userLocation;
+ this.useExistingData = useData;
+ }
+
+ public int compare(POI poi1, POI poi2) {
+ if (poi1.distTo == -1 || !useExistingData) {
+ poi1.distTo = userLocation.distanceTo(poi1.point);
+ }
+ if (poi2.distTo == -1 || !useExistingData) {
+ poi2.distTo = userLocation.distanceTo(poi2.point);
+ }
+ return poi1.distTo - poi2.distTo;
+ }
+
+}
diff --git a/src/net/cbaines/suma/POIFavouriteComparator.java b/src/net/cbaines/suma/POIFavouriteComparator.java
new file mode 100644
index 0000000..94148d4
--- /dev/null
+++ b/src/net/cbaines/suma/POIFavouriteComparator.java
@@ -0,0 +1,40 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.util.Comparator;
+
+public class POIFavouriteComparator implements Comparator<POI> {
+
+ public int compare(POI poi1, POI poi2) {
+ if (poi1.favourite) {
+ if (poi2.favourite) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if (poi2.favourite) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+}
diff --git a/src/net/cbaines/suma/POIView.java b/src/net/cbaines/suma/POIView.java
new file mode 100644
index 0000000..733cd0f
--- /dev/null
+++ b/src/net/cbaines/suma/POIView.java
@@ -0,0 +1,116 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class POIView extends LinearLayout {
+
+ private final static String TAG = "POIView";
+
+ private final TextView name;
+ private final TextView dist;
+
+ private LayoutParams textLayoutParams;
+
+ final int width;
+
+ public POIView(Context context, POI poi) {
+ this(context, poi, -1);
+ }
+
+ public POIView(Context context, POI poi, int distInM) {
+ super(context);
+
+ Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+ width = display.getWidth();
+ // int height = display.getHeight();
+
+ this.setOrientation(HORIZONTAL);
+
+ name = new TextView(context);
+ name.setTextSize(22f);
+ name.setGravity(Gravity.LEFT);
+
+ dist = new TextView(context);
+ dist.setTextSize(22f);
+ dist.setGravity(Gravity.RIGHT);
+
+ textLayoutParams = new LayoutParams(width - (width / 4), LayoutParams.WRAP_CONTENT);
+ LayoutParams distLayoutParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
+
+ setPOIAndDist(poi, distInM);
+
+ addView(name, textLayoutParams);
+ addView(dist, distLayoutParams);
+ }
+
+ public void setPOI(POI poi) {
+ setPOIAndDist(poi, -1);
+ }
+
+ public void setPOIAndDist(POI poi, int distInM) {
+
+ // Log.i(TAG, "Looking at poi " + poi.id);
+
+ if (poi.type == POI.BUILDING) {
+ Building building = (Building) poi;
+ // Log.i(TAG, "Its a building of name " + building.name);
+
+ name.setText(building.name + " (" + building.id + ")");
+ } else if (poi.type == POI.BUS_STOP) {
+
+ BusStop busStop = (BusStop) poi;
+ // Log.i(TAG, "Its a bus stop of description " + busStop.description);
+
+ name.setText(busStop.description + " (" + busStop.id + ")");
+ } else if (poi.type == POI.SITE) {
+
+ Site site = (Site) poi;
+ // Log.i(TAG, "Its a site of name " + site.name);
+
+ name.setText(site.name + " (" + site.id + ")");
+ } else {
+ Log.w(TAG, "Cant identify " + poi.type);
+
+ name.setText(poi.id);
+ }
+
+ textLayoutParams = new LayoutParams(width - (width / 4), LayoutParams.WRAP_CONTENT);
+
+ if (distInM != -1) {
+ textLayoutParams.width = width - (width / 4);
+ name.requestLayout();
+ dist.setText(String.valueOf(distInM) + "m");
+ } else {
+ textLayoutParams.width = LayoutParams.FILL_PARENT;
+ name.requestLayout();
+ dist.setText("");
+ // Log.w("POIView", "No dist avalible for S" + poi.id);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/net/cbaines/suma/Polygon.java b/src/net/cbaines/suma/Polygon.java
new file mode 100644
index 0000000..5020a33
--- /dev/null
+++ b/src/net/cbaines/suma/Polygon.java
@@ -0,0 +1,53 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.io.Serializable;
+
+import org.osmdroid.util.GeoPoint;
+
+public class Polygon implements Serializable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3029139596630651715L;
+
+ final GeoPoint[] points;
+
+ Polygon() {
+ points = null;
+ }
+
+ Polygon(GeoPoint[] points) {
+ this.points = points;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Polygon ");
+
+ for (GeoPoint point : points) {
+ builder.append(point.getLatitudeE6() + " " + point.getLongitudeE6());
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/src/net/cbaines/suma/PreferencesActivity.java b/src/net/cbaines/suma/PreferencesActivity.java
new file mode 100644
index 0000000..b7c1d89
--- /dev/null
+++ b/src/net/cbaines/suma/PreferencesActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+public class PreferencesActivity extends PreferenceActivity {
+ boolean CheckboxPreference;
+ String ListPreference;
+ String editTextPreference;
+ String ringtonePreference;
+ String secondEditTextPreference;
+ String customPref;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.preferences);
+ }
+
+} \ No newline at end of file
diff --git a/src/net/cbaines/suma/RouteColorConstants.java b/src/net/cbaines/suma/RouteColorConstants.java
new file mode 100644
index 0000000..ba4fa36
--- /dev/null
+++ b/src/net/cbaines/suma/RouteColorConstants.java
@@ -0,0 +1,30 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import android.graphics.Color;
+
+public interface RouteColorConstants {
+ public final int U1 = Color.rgb(0, 139, 208);
+ public final int U1N = Color.rgb(0, 47, 107); // Dark blue
+ public final int U2 = Color.rgb(226, 0, 26);
+ public final int U6 = Color.rgb(247, 168, 0);
+ public final int U9 = Color.rgb(231, 82, 148); // Pink
+}
diff --git a/src/net/cbaines/suma/RouteOverlayItem.java b/src/net/cbaines/suma/RouteOverlayItem.java
new file mode 100644
index 0000000..77df6dc
--- /dev/null
+++ b/src/net/cbaines/suma/RouteOverlayItem.java
@@ -0,0 +1,37 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.util.ArrayList;
+
+import org.osmdroid.util.GeoPoint;
+import org.osmdroid.views.overlay.OverlayItem;
+
+public class RouteOverlayItem extends OverlayItem {
+
+ ArrayList<? extends POI> route;
+
+ public RouteOverlayItem(String aTitle, String aDescription, ArrayList<? extends POI> route) {
+ super(aTitle, aDescription, new GeoPoint(0, 0));
+ this.route = route;
+
+ }
+
+}
diff --git a/src/net/cbaines/suma/RouteStops.java b/src/net/cbaines/suma/RouteStops.java
new file mode 100644
index 0000000..8375785
--- /dev/null
+++ b/src/net/cbaines/suma/RouteStops.java
@@ -0,0 +1,58 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "routestops")
+public class RouteStops {
+ public final static String STOP_ID_FIELD_NAME = "stop_id";
+ public final static String ROUTE_ID_FIELD_NAME = "route_id";
+ public final static String SEQUENCE_ID_FIELD_NAME = "sequence";
+
+ /**
+ * This id is generated by the database and set on the object when it is passed to the create method. An id is needed in case we need to update or delete
+ * this object in the future.
+ */
+ @DatabaseField(generatedId = true)
+ int id;
+
+ @DatabaseField
+ int sequence;
+
+ // This is a foreign object which just stores the id from the User object in this table.
+ @DatabaseField(foreign = true, columnName = STOP_ID_FIELD_NAME, indexName = "routestops_routestop_idx")
+ BusStop stop;
+
+ // This is a foreign object which just stores the id from the Post object in this table.
+ @DatabaseField(foreign = true, columnName = ROUTE_ID_FIELD_NAME, indexName = "routestops_routestop_idx")
+ BusRoute route;
+
+ RouteStops() {
+ // for ormlite
+ }
+
+ public RouteStops(BusStop stop, BusRoute route, int sequence) {
+ this.stop = stop;
+ this.route = route;
+ this.sequence = sequence;
+ }
+}
diff --git a/src/net/cbaines/suma/Site.java b/src/net/cbaines/suma/Site.java
new file mode 100644
index 0000000..0447d8a
--- /dev/null
+++ b/src/net/cbaines/suma/Site.java
@@ -0,0 +1,55 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import org.osmdroid.util.GeoPoint;
+
+import com.j256.ormlite.field.DataType;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "sites")
+public class Site extends POI {
+
+ public static final String NAME_FIELD_NAME = "name";
+ public static final String OUTLINE_FIELD_NAME = "outline";
+
+ @DatabaseField(canBeNull = false)
+ String name;
+
+ @DatabaseField(dataType = DataType.SERIALIZABLE, canBeNull = true)
+ Polygon outline;
+
+ Site(String id, String name, GeoPoint point, Polygon outline) {
+ super(id, point);
+ this.name = name;
+ this.outline = outline;
+ this.type = POI.SITE;
+ }
+
+ Site() {
+ this.type = POI.SITE;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+}
diff --git a/src/net/cbaines/suma/SouthamptonUniversityMapActivity.java b/src/net/cbaines/suma/SouthamptonUniversityMapActivity.java
new file mode 100644
index 0000000..430bd4f
--- /dev/null
+++ b/src/net/cbaines/suma/SouthamptonUniversityMapActivity.java
@@ -0,0 +1,1405 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.osmdroid.DefaultResourceProxyImpl;
+import org.osmdroid.ResourceProxy;
+import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
+import org.osmdroid.util.GeoPoint;
+import org.osmdroid.views.MapController;
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.overlay.MyLocationOverlay;
+import org.osmdroid.views.overlay.Overlay;
+import org.osmdroid.views.overlay.PathOverlay;
+import org.osmdroid.views.overlay.ScaleBarOverlay;
+import org.osmdroid.views.util.constants.MapViewConstants;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.graphics.Color;
+import android.graphics.DashPathEffect;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.CheckBox;
+import android.widget.ExpandableListView;
+import android.widget.ExpandableListView.OnChildClickListener;
+import android.widget.TextView;
+
+import com.j256.ormlite.android.apptools.OrmLiteBaseActivity;
+import com.j256.ormlite.dao.Dao;
+
+public class SouthamptonUniversityMapActivity extends OrmLiteBaseActivity<DatabaseHelper> implements MapViewConstants, Runnable, RouteColorConstants,
+ OnChildClickListener, OnItemClickListener, OnItemLongClickListener, OnSharedPreferenceChangeListener {
+
+ private boolean useBundledDatabase = true;
+
+ private MapView mapView;
+ private MapController mapController;
+ private ResourceProxy mResourceProxy;
+
+ private long startTime;
+
+ static final int VIEW_DIALOG_ID = 0;
+ static final int FAVOURITE_DIALOG_ID = 1;
+
+ private HashMap<String, Overlay> overlays = new HashMap<String, Overlay>();
+ private HashMap<String, Overlay> pastOverlays;
+
+ private ScaleBarOverlay scaleBarOverlay;
+ private MyLocationOverlay myLocationOverlay;
+ private BuildingNumOverlay residentialBuildingOverlay;
+ private BuildingNumOverlay nonResidentialBuildingOverlay;
+ private BusStopOverlay busStopOverlay;
+ private HashMap<Site, PathOverlay> siteOverlays;
+ private HashMap<BusRoute, PathOverlay> routeOverlays;
+
+ private String[] busRoutes;
+ private String[] buildingTypes;
+ private String[] other;
+ private String[] groupHeadings;
+ private String[] siteNames;
+
+ private FavouriteDialog favDialog;
+
+ private SouthamptonUniversityMapActivity instance;
+
+ private static final String TAG = "SUM";
+
+ @SuppressWarnings("unchecked")
+ public void onCreate(Bundle savedInstanceState) {
+ startTime = System.currentTimeMillis();
+
+ super.onCreate(savedInstanceState);
+
+ instance = this;
+
+ final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ final SharedPreferences activityPrefs = getPreferences(0);
+
+ if (!sharedPrefs.contains("GPSEnabled")) {
+ sharedPrefs.edit().putBoolean("GPSEnabled", true).commit();
+ }
+ if (!sharedPrefs.contains("liveBusTimesEnabled")) {
+ sharedPrefs.edit().putBoolean("liveBusTimesEnabled", true).commit();
+ }
+
+ Log.i(TAG, "GPS Enabled " + sharedPrefs.getBoolean("GPSEnabled", false));
+ Log.i(TAG, "Live Bus Times Enabled " + sharedPrefs.getBoolean("liveBusTimesEnabled", false));
+
+ setContentView(R.layout.main);
+
+ Log.i(TAG, "Finished setting content view " + (System.currentTimeMillis() - startTime));
+
+ busRoutes = getResources().getStringArray(R.array.uniLinkBusRoutes);
+ buildingTypes = getResources().getStringArray(R.array.buildingTypes);
+ other = getResources().getStringArray(R.array.utilityOverlays);
+ groupHeadings = getResources().getStringArray(R.array.preferencesHeadings);
+
+ mapView = (MapView) this.findViewById(R.id.mapview);
+ mapView.setTileSource(TileSourceFactory.MAPNIK);
+ mapView.setBuiltInZoomControls(true);
+ mapView.setMultiTouchControls(true);
+
+ pastOverlays = (HashMap<String, Overlay>) getLastNonConfigurationInstance();
+
+ Log.i(TAG, "Instantiating myLocationOverlay");
+ // SensorManager mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); This code in the following constructor causes problems in
+ // some emulators, disable there sensors to fix.
+ myLocationOverlay = new MyLocationOverlay(instance, mapView);
+ Log.i(TAG, "Finished instantiating myLocationOverlay");
+
+ mapController = mapView.getController();
+ mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
+
+ GeoPoint userLocation = myLocationOverlay.getMyLocation();
+ if (userLocation == null) {
+ userLocation = new GeoPoint(50935551, -1393488); // ECS
+ }
+
+ mapController.setZoom(15);
+ mapController.setCenter(userLocation);
+
+ Editor editor = activityPrefs.edit();
+ editor.putBoolean("first_run", false);
+ editor.commit();
+
+ new Thread(this).start();
+ }
+
+ public void onResume() {
+ super.onResume();
+ Log.i(TAG, "OnResume");
+ if (myLocationOverlay != null) {
+ final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ final SharedPreferences activityPrefs = getPreferences(0);
+
+ if (activityPrefs.getBoolean("Other:Compass", false)) {
+ myLocationOverlay.enableCompass();
+ } else {
+ myLocationOverlay.disableCompass();
+ }
+
+ if (activityPrefs.getBoolean("Other:My Location", false) && sharedPrefs.getBoolean("GPSEnabled", false)) {
+ myLocationOverlay.enableMyLocation();
+ } else {
+ myLocationOverlay.disableMyLocation();
+ }
+ }
+ }
+
+ public void onPause() {
+ super.onResume();
+ Log.i(TAG, "OnPause");
+ if (myLocationOverlay != null) {
+ myLocationOverlay.disableMyLocation();
+ myLocationOverlay.disableCompass();
+ }
+ }
+
+ public void finish() {
+ super.finish();
+ }
+
+ @Override
+ public Object onRetainNonConfigurationInstance() {
+ return overlays;
+ }
+
+ public void run() {
+ Log.i(TAG, "Begining loading the map overlay stuff " + (System.currentTimeMillis() - startTime));
+
+ Log.i(TAG, "Begining loading databases " + (System.currentTimeMillis() - startTime));
+
+ DatabaseHelper helper = getHelper();
+ Log.i(TAG, "Got the helper");
+
+ boolean dbExist = helper.checkDataBase();
+
+ if (dbExist) {
+ // do nothing - database already exist
+ } else {
+
+ if (useBundledDatabase) {
+ try {
+ helper.copyDataBase();
+ Log.i(TAG, "Out of copy database");
+ } catch (IOException ioe) {
+ throw new Error("Unable to create database");
+ }
+ } else {
+ Thread buildingThread = null;
+ Thread busStopThread = null;
+ Thread siteThread = null;
+
+ Log.i(TAG, "Begining loading databases " + (System.currentTimeMillis() - startTime));
+ try {
+ Dao<Building, String> buildingDao;
+
+ buildingDao = helper.getBuildingDao();
+
+ long buildingCount = buildingDao.countOf();
+ Log.i(TAG, "Building count " + buildingCount);
+ if (buildingCount < 260) {
+ buildingThread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ DataManager.loadBuildings(instance);
+ Log.i(TAG, "Loaded building database " + (System.currentTimeMillis() - startTime));
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ buildingThread.start();
+ }
+
+ Dao<BusStop, String> busStopDao = helper.getBusStopDao();
+ Dao<BusRoute, Integer> busRouteDao = helper.getBusRouteDao();
+ Dao<RouteStops, Integer> routeStopsDao = helper.getRouteStopsDao();
+
+ long busStopCount = busStopDao.countOf();
+ long busRouteCount = busRouteDao.countOf();
+ long routeStopsCount = routeStopsDao.countOf();
+
+ Log.i(TAG, "BusStop count " + busStopCount);
+ Log.i(TAG, "BusRoute count " + busRouteCount);
+ Log.i(TAG, "RouteStops count " + routeStopsCount);
+ if (busStopCount < 217 || busRouteCount < 5 || routeStopsCount < 327) {
+ busStopThread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ DataManager.loadBusData(instance, true);
+ Log.i(TAG, "Loaded bus stop database " + (System.currentTimeMillis() - startTime));
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ busStopThread.start();
+ }
+
+ Dao<Site, String> siteDao = helper.getSiteDao();
+
+ long siteCount = siteDao.countOf();
+ Log.i(TAG, "Sites count " + siteCount);
+ if (siteCount < 21) {
+ siteThread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ DataManager.loadSiteData(instance);
+ Log.i(TAG, "Loaded site database " + (System.currentTimeMillis() - startTime));
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ siteThread.start();
+ }
+
+ while (true) {
+ if ((buildingThread == null || !buildingThread.isAlive()) && (busStopThread == null || !busStopThread.isAlive())
+ && (siteThread == null || !siteThread.isAlive()))
+ break;
+
+ Thread.yield();
+ }
+
+ try {
+ siteNames = new String[(int) siteDao.countOf()];
+
+ int i = 0;
+ for (Site site : siteDao) {
+ siteNames[i] = site.name;
+ i++;
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ SharedPreferences mainPrefs = getPreferences(0);
+ if (mainPrefs.getBoolean("first_run", true)) {
+ Log.i(TAG, "Changing button in intro");
+ }
+
+ Log.i(TAG, "Finished loading databases " + (System.currentTimeMillis() - startTime));
+
+ } catch (SQLException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ }
+
+ try {
+ setupActivityPrefs();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ createOverlays();
+ Log.i(TAG, "Finished seting in motion the creation of the overlays " + (System.currentTimeMillis() - startTime));
+
+ }
+
+ private void setupActivityPrefs() throws SQLException {
+ Log.i(TAG, "Begining setting up preferences");
+
+ SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ int size = (int) getHelper().getSiteDao().countOf();
+ ArrayList<Site> sites = new ArrayList<Site>(size);
+
+ try {
+ sites.addAll(getHelper().getSiteDao().queryForAll());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ siteNames = new String[size];
+ for (int i = 0; i < size; i++) {
+ siteNames[i] = sites.get(i).name;
+ }
+
+ SharedPreferences activityPrefs = getPreferences(0);
+ Editor editor = activityPrefs.edit();
+
+ for (int heading = 0; heading < groupHeadings.length; heading++) {
+ if (heading == 0 || heading == 1) {
+ for (int child = 0; child < busRoutes.length; child++) {
+ if (!activityPrefs.contains(groupHeadings[heading] + ":" + busRoutes[child])) {
+ editor.putBoolean(groupHeadings[heading] + ":" + busRoutes[child], true);
+ }
+ }
+ } else if (heading == 2) {
+ for (int child = 0; child < buildingTypes.length; child++) {
+ if (!activityPrefs.contains(groupHeadings[heading] + ":" + buildingTypes[child])) {
+ editor.putBoolean(groupHeadings[heading] + ":" + buildingTypes[child], true);
+ }
+ }
+ } else if (heading == 3) {
+ for (int child = 0; child < sites.size(); child++) {
+ if (!activityPrefs.contains(groupHeadings[heading] + ":" + sites.get(child))) {
+ editor.putBoolean(groupHeadings[heading] + ":" + sites.get(child), true);
+ }
+ }
+ } else if (heading == 4) {
+ for (int child = 0; child < other.length; child++) {
+ if (!activityPrefs.contains(groupHeadings[heading] + ":" + other[child])) {
+ editor.putBoolean(groupHeadings[heading] + ":" + other[child], true);
+ }
+ }
+ }
+ }
+
+ editor.commit();
+
+ activityPrefs.registerOnSharedPreferenceChangeListener(this);
+ sharedPrefs.registerOnSharedPreferenceChangeListener(this);
+
+ Log.i(TAG, "Finished setting up preferences");
+ }
+
+ private void createOverlays() {
+ Log.i(TAG, "Began creating overlays at " + (System.currentTimeMillis() - startTime));
+
+ if (pastOverlays != null) {
+ Log.i(TAG, "Able to recover some/all of the overlays from a previous activity");
+ } else {
+ Log.i(TAG, "Unable to recover overlays");
+ }
+
+ final OverlayRankComparator comparator = new OverlayRankComparator(getPreferences(0));
+ final SharedPreferences activityPrefs = getPreferences(0);
+
+ Thread utilityOverlayCreation = new Thread(new Runnable() {
+ public void run() {
+ Log.i(TAG, "Begining the creation of the utility overlays");
+
+ if (pastOverlays != null) {
+ scaleBarOverlay = (ScaleBarOverlay) pastOverlays.get("Other:Scale Bar");
+
+ if (scaleBarOverlay != null && myLocationOverlay != null) {
+ overlays.put("Other:Scale Bar", scaleBarOverlay);
+ Log.i(TAG, "Finished restoring utility overlays " + (System.currentTimeMillis() - startTime));
+ return;
+ }
+ }
+
+ scaleBarOverlay = new ScaleBarOverlay(instance);
+ scaleBarOverlay.setEnabled(activityPrefs.getBoolean("Other:Scale Bar", true));
+
+ overlays.put("Other:Scale Bar", scaleBarOverlay);
+
+ Log.i(TAG, "Finished creating utility overlays " + (System.currentTimeMillis() - startTime));
+
+ }
+ });
+
+ utilityOverlayCreation.start();
+
+ Runnable utilityOverlayApplication = new Runnable() {
+ public void run() {
+ Log.i(TAG, "Begining the application of the utility overlays");
+
+ mapView.getOverlays().add(scaleBarOverlay);
+
+ mapView.getOverlays().add(myLocationOverlay);
+
+ Log.v(TAG, "Applyed the utility overlays, now sorting them");
+
+ Collections.sort(mapView.getOverlays(), comparator);
+
+ Log.v(TAG, "Finished sorting the utility overlays them, now applying them");
+
+ mapView.invalidate();
+
+ Log.i(TAG, "Finished loading utility overlays " + (System.currentTimeMillis() - startTime));
+
+ }
+ };
+
+ Thread routeOverlayCreation = new Thread(new Runnable() {
+ public void run() {
+
+ try {
+ Log.i(TAG, "Begining to create the route overlays");
+
+ SharedPreferences mainPrefs = getPreferences(0);
+
+ routeOverlays = new HashMap<BusRoute, PathOverlay>(5);
+
+ Dao<BusRoute, Integer> busRouteDao = getHelper().getBusRouteDao();
+
+ for (Iterator<BusRoute> routeIter = busRouteDao.iterator(); routeIter.hasNext();) {
+ BusRoute route = routeIter.next();
+
+ Log.v(TAG, "Looking at route " + route.code);
+
+ if (pastOverlays != null) {
+ PathOverlay routeOverlay = (PathOverlay) pastOverlays.get("Bus Routes:" + route.code);
+ if (routeOverlay != null) {
+ Log.i(TAG, "Restored " + route.code + " route overlay");
+ routeOverlays.put(route, routeOverlay);
+ overlays.put("Bus Routes:" + route.code, routeOverlay);
+ continue;
+ }
+ }
+
+ InputStream resource = null;
+ int colour = 0;
+ if (route.code.equals("U1")) {
+ resource = getResources().openRawResource(R.raw.u1);
+ colour = U1;
+
+ // TODO Is this a route like U1N or, something else, this hack works somewhat for now?
+ PathOverlay routeOverlayU1E = DataManager.getRoutePath(getResources().openRawResource(R.raw.u1e), colour, mResourceProxy);
+ routeOverlayU1E.getPaint().setAntiAlias(true);
+ routeOverlayU1E.getPaint().setAlpha(145);
+ routeOverlayU1E.getPaint().setStrokeWidth(12);
+ routeOverlayU1E.getPaint().setPathEffect(new DashPathEffect(new float[] { 20, 16 }, 0));
+ routeOverlayU1E.setEnabled(mainPrefs.getBoolean("Bus Routes:" + route.code, true));
+
+ routeOverlays.put(new BusRoute(1000, "U1E", "U1e Route Label"), routeOverlayU1E);
+ overlays.put("Bus Routes:" + route.code + "E", routeOverlayU1E);
+ } else if (route.code.equals("U1N")) {
+ resource = getResources().openRawResource(R.raw.u1n);
+ colour = U1N;
+ } else if (route.code.equals("U2")) {
+ resource = getResources().openRawResource(R.raw.u2);
+ colour = U2;
+ } else if (route.code.equals("U6")) {
+ resource = getResources().openRawResource(R.raw.u6);
+ colour = U6;
+ } else if (route.code.equals("U9")) {
+ resource = getResources().openRawResource(R.raw.u9);
+ colour = U9;
+ } else {
+ continue;
+ }
+
+ PathOverlay routeOverlay = DataManager.getRoutePath(resource, colour, mResourceProxy);
+
+ Log.i(TAG, "Path overlay has " + routeOverlay.getNumberOfPoints() + " points");
+
+ routeOverlay.getPaint().setAntiAlias(true);
+ routeOverlay.getPaint().setAlpha(145);
+ routeOverlay.getPaint().setStrokeWidth(12);
+ routeOverlay.setEnabled(mainPrefs.getBoolean("Bus Routes:" + route.code, true));
+
+ routeOverlays.put(route, routeOverlay);
+ overlays.put("Bus Routes:" + route.code, routeOverlay);
+
+ }
+
+ Log.i(TAG, "Finished loading routes " + (System.currentTimeMillis() - startTime));
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ routeOverlayCreation.start();
+
+ Runnable routeOverlayApplication = new Runnable() {
+ public void run() {
+ Log.i(TAG, "Begining applying the route overlays, number of route overlays = " + routeOverlays.size());
+
+ for (PathOverlay routeOverlay : routeOverlays.values()) {
+ Log.v(TAG, "Added route overlay");
+ mapView.getOverlays().add(routeOverlay);
+ }
+
+ Log.v(TAG, "Added the route overlays, now sorting them");
+
+ Collections.sort(mapView.getOverlays(), comparator);
+
+ Log.v(TAG, "Finished sorting the route overlays them, now applying them");
+
+ mapView.invalidate();
+
+ Log.i(TAG, "Finished loading route overlays " + (System.currentTimeMillis() - startTime));
+ }
+ };
+
+ Thread siteOverlayCreation = new Thread(new Runnable() {
+ public void run() {
+ Log.i(TAG, "Begining the creation of the site overlays");
+
+ SharedPreferences mainPrefs = getPreferences(0);
+
+ try {
+
+ Dao<Site, String> siteDao = getHelper().getSiteDao();
+ siteOverlays = new HashMap<Site, PathOverlay>((int) siteDao.countOf());
+
+ for (Site site : siteDao) {
+
+ if (pastOverlays != null) {
+ PathOverlay overlay = (PathOverlay) pastOverlays.get("Site Outlines:" + site.name);
+ if (overlay != null) {
+ Log.i(TAG, "Restored " + site.name + " site overlay");
+ siteOverlays.put(site, overlay);
+ overlays.put("Site Outlines:" + site.name, overlay);
+ continue;
+ }
+ }
+
+ PathOverlay overlay = new PathOverlay(Color.BLUE, instance);
+ Paint paint = overlay.getPaint();
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(1.5f);
+ for (int i = 0; i < site.outline.points.length; i++) {
+ overlay.addPoint(site.outline.points[i]);
+ }
+ overlay.addPoint(site.outline.points[0]);
+
+ overlay.setEnabled(mainPrefs.getBoolean("Site Outlines:" + site.name, true));
+
+ siteOverlays.put(site, overlay);
+ overlays.put("Site Outlines:" + site.name, overlay);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ Log.i(TAG, "Finished creating site overlays " + (System.currentTimeMillis() - startTime));
+
+ }
+ });
+
+ siteOverlayCreation.start();
+
+ Runnable siteOverlayApplication = new Runnable() {
+ public void run() {
+ Log.i(TAG, "Begining applying the site overlays, number of site overlays = " + siteOverlays.size());
+
+ for (PathOverlay siteOverlay : siteOverlays.values()) {
+ Log.d(TAG, "Added site overlay");
+ mapView.getOverlays().add(siteOverlay);
+ }
+
+ Log.v(TAG, "Added the site overlays, now sorting them");
+
+ Collections.sort(mapView.getOverlays(), comparator);
+
+ Log.v(TAG, "Finished sorting the site overlays them, now applying them");
+
+ mapView.invalidate();
+
+ Log.i(TAG, "Finished loading site overlays " + (System.currentTimeMillis() - startTime));
+ }
+ };
+
+ Thread buildingOverlayCreation = new Thread(new Runnable() {
+ public void run() {
+ Log.i(TAG, "Begining the creation of the building overlays");
+ try {
+ if (pastOverlays != null) {
+ residentialBuildingOverlay = (BuildingNumOverlay) pastOverlays.get("Buildings:Residential");
+ nonResidentialBuildingOverlay = (BuildingNumOverlay) pastOverlays.get("Buildings:Non-Residential");
+ if (residentialBuildingOverlay != null && nonResidentialBuildingOverlay != null) {
+ overlays.put("Buildings:" + buildingTypes[0], residentialBuildingOverlay);
+ overlays.put("Buildings:" + buildingTypes[1], nonResidentialBuildingOverlay);
+
+ Log.i(TAG, "Restored building overlays");
+ return;
+ }
+ }
+
+ SharedPreferences mainPrefs = getPreferences(0);
+
+ ArrayList<Building> residentialBuildings = new ArrayList<Building>();
+ ArrayList<Building> nonResidentialBuildings = new ArrayList<Building>();
+
+ Dao<Building, String> buildingDao = getHelper().getBuildingDao();
+
+ for (Building building : buildingDao) {
+ // Log.v(TAG, "Looking at building " + building.id);
+ if (building.residential == true) {
+ // Log.v(TAG, "Its residential");
+ if (building.favourite) {
+ // Log.v(TAG, "Its residential and a favourite");
+ residentialBuildings.add(building);
+ } else {
+ // Log.v(TAG, "Its residential and not a favourite");
+ residentialBuildings.add(0, building);
+ }
+ } else {
+ if (building.favourite) {
+ // Log.v(TAG, "Its not residential and a favourite");
+ nonResidentialBuildings.add(building);
+ } else {
+ // Log.v(TAG, "Its not residential and not a favourite");
+ nonResidentialBuildings.add(0, building);
+ }
+ }
+ }
+
+ residentialBuildingOverlay = new BuildingNumOverlay(instance, residentialBuildings);
+ nonResidentialBuildingOverlay = new BuildingNumOverlay(instance, nonResidentialBuildings);
+
+ residentialBuildingOverlay.setEnabled(mainPrefs.getBoolean("Buildings:Residential", false));
+ nonResidentialBuildingOverlay.setEnabled(mainPrefs.getBoolean("Buildings:Non-Residential", false));
+
+ overlays.put("Buildings:" + buildingTypes[0], residentialBuildingOverlay);
+ overlays.put("Buildings:" + buildingTypes[1], nonResidentialBuildingOverlay);
+
+ Log.i(TAG, "Finished creating building overlays " + (System.currentTimeMillis() - startTime));
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ }
+ });
+
+ buildingOverlayCreation.start();
+
+ Runnable buildingOverlayApplication = new Runnable() {
+ public void run() {
+ Log.i(TAG, "Begining applying the building overlays");
+
+ mapView.getOverlays().add(residentialBuildingOverlay);
+ mapView.getOverlays().add(nonResidentialBuildingOverlay);
+
+ Log.v(TAG, "Added the building overlays, now sorting them");
+
+ Collections.sort(mapView.getOverlays(), comparator);
+
+ Log.v(TAG, "Finished sorting the building overlays, now applying them");
+
+ mapView.invalidate();
+
+ Log.i(TAG, "Finished loading building overlays " + (System.currentTimeMillis() - startTime));
+ }
+ };
+
+ Thread busStopOverlayCreation = new Thread(new Runnable() {
+
+ public void run() {
+ Log.i(TAG, "Begining the creation of the bus stop overlay");
+
+ if (pastOverlays != null) {
+ busStopOverlay = (BusStopOverlay) pastOverlays.get("BusStops");
+ if (busStopOverlay != null) {
+ overlays.put("BusStops", busStopOverlay);
+
+ Log.i(TAG, "Restored bus stop overlays");
+ return;
+ }
+ }
+
+ try {
+ SharedPreferences mainPrefs = getPreferences(0);
+
+ busStopOverlay = new BusStopOverlay(instance);
+ busStopOverlay.setRoutes(0, mainPrefs.getBoolean("Bus Stops:U1", false));
+ busStopOverlay.setRoutes(1, mainPrefs.getBoolean("Bus Stops:U1N", false));
+ busStopOverlay.setRoutes(2, mainPrefs.getBoolean("Bus Stops:U2", false));
+ busStopOverlay.setRoutes(3, mainPrefs.getBoolean("Bus Stops:U6", false));
+ busStopOverlay.setRoutes(4, mainPrefs.getBoolean("Bus Stops:U9", false));
+
+ overlays.put("BusStops", busStopOverlay);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ Log.i(TAG, "Finished creating the bus stops overlay " + (System.currentTimeMillis() - startTime));
+ }
+ });
+
+ busStopOverlayCreation.start();
+
+ Runnable busStopOverlayApplication = new Runnable() {
+ public void run() {
+ Log.i(TAG, "Begining applying the bus stop overlay");
+
+ mapView.getOverlays().add(busStopOverlay);
+
+ Log.v(TAG, "Added the bus stop overlay, now sorting them");
+
+ Collections.sort(mapView.getOverlays(), comparator);
+
+ Log.v(TAG, "Finished sorting the bus stop overlay, now applying them");
+
+ mapView.invalidate();
+
+ Log.i(TAG, "Finished loading bus stop overlay " + (System.currentTimeMillis() - startTime));
+ }
+ };
+
+ while (utilityOverlayCreation != null || routeOverlayCreation != null || siteOverlayCreation != null || buildingOverlayCreation != null
+ || busStopOverlayCreation != null) {
+ if (utilityOverlayCreation != null && !utilityOverlayCreation.isAlive()) {
+ mapView.post(utilityOverlayApplication);
+ utilityOverlayCreation = null;
+ }
+
+ if (routeOverlayCreation != null && !routeOverlayCreation.isAlive()) {
+ mapView.post(routeOverlayApplication);
+ routeOverlayCreation = null;
+ }
+
+ if (siteOverlayCreation != null && !siteOverlayCreation.isAlive()) {
+ mapView.post(siteOverlayApplication);
+ siteOverlayCreation = null;
+ }
+
+ if (buildingOverlayCreation != null && !buildingOverlayCreation.isAlive()) {
+ mapView.post(buildingOverlayApplication);
+ buildingOverlayCreation = null;
+ }
+
+ if (busStopOverlayCreation != null && !busStopOverlayCreation.isAlive()) {
+ mapView.post(busStopOverlayApplication);
+ busStopOverlayCreation = null;
+ }
+
+ Thread.yield();
+ }
+
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.map_menu, menu);
+ return true;
+
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle item selection
+ switch (item.getItemId()) {
+ case R.id.menu_find:
+ Intent i = new Intent(SouthamptonUniversityMapActivity.this, FindActivity.class);
+ startActivityForResult(i, 0);
+ return true;
+ case R.id.menu_preferences:
+ Intent settingsActivity = new Intent(getBaseContext(), PreferencesActivity.class);
+ startActivity(settingsActivity);
+ return true;
+ case R.id.menu_find_my_location:
+ final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ if (sharedPrefs.getBoolean("GPSEnabled", false)) {
+ GeoPoint userLocation = myLocationOverlay.getMyLocation();
+ if (userLocation != null) {
+ Log.i(TAG, "Found user location, scrolling to " + userLocation);
+ mapController.animateTo(userLocation);
+ myLocationOverlay.enableFollowLocation();
+ }
+ } else {
+ DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ Editor editor = sharedPrefs.edit();
+ editor.putBoolean("GPSEnabled", true);
+ editor.commit();
+ break;
+
+ case DialogInterface.BUTTON_NEGATIVE:
+ // No button clicked
+ break;
+ }
+ }
+ };
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setMessage("GPS is not enabled, do you wish to enable it?").setPositiveButton("Yes", dialogClickListener)
+ .setNegativeButton("No", dialogClickListener).show();
+ }
+
+ return true;
+ case R.id.menu_view:
+ Log.i(TAG, "Showing view dialog");
+ showDialog(VIEW_DIALOG_ID);
+ return false;
+ case R.id.menu_favourites:
+ Log.i(TAG, "Showing favourite dialog");
+ showDialog(FAVOURITE_DIALOG_ID);
+ if (favDialog != null) {
+ favDialog.refresh();
+ } else {
+ Log.e(TAG, "Very wierd, just tried to launch the favourite's dialog, but its null?");
+ }
+ return false;
+ case R.id.menu_about:
+ Intent aboutIntent = new Intent(SouthamptonUniversityMapActivity.this, AboutActivity.class);
+ startActivityForResult(aboutIntent, 0);
+ return true;
+ default:
+ Log.e(TAG, "No known menu option selected");
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ public boolean onSearchRequested() {
+ Intent i = new Intent(SouthamptonUniversityMapActivity.this, FindActivity.class);
+ startActivityForResult(i, 0);
+ return false;
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ Log.i(TAG, "Got activity result");
+ if (resultCode == RESULT_OK) {
+
+ POI poi = null;
+ Bundle bundle = data.getExtras();
+ if (bundle == null) {
+ Log.i(TAG, "Bundle is null");
+ } else {
+ String poiId = (String) bundle.get("poi");
+ if (poiId != null) {
+ Log.i(TAG, "Got id " + poiId);
+ try {
+ poi = getHelper().getBuildingDao().queryForId(poiId);
+ if (poi == null) {
+ poi = getHelper().getBusStopDao().queryForId(poiId);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ if (poi == null) {
+ Log.e(TAG, "Could not find poi " + poiId + " in onActivityResult");
+ } else {
+ if (myLocationOverlay != null) {
+ // It could be null if it has not been enabled
+ myLocationOverlay.disableFollowLocation();
+ }
+ mapController.setZoom(20);
+ mapController.setCenter(poi.point);
+
+ }
+ } else {
+ Log.i(TAG, "Got null poi id");
+
+ // mapController.setZoom(15);
+ // mapController.setCenter(new GeoPoint(50935551, -1393488));
+ }
+
+ // This handles the possible change in favourite state caused by the user within the BusTimeActivity
+ try {
+ String busStopID = bundle.getString("busStopChanged");
+ if (busStopID != null && busStopID.length() != 0) {
+ Log.v(TAG, "Got a busStop id back from the BusTimeActivity " + busStopID);
+ BusStop busStop = getHelper().getBusStopDao().queryForId(busStopID);
+
+ busStopOverlay.refresh(busStop); // This does not invalidate the map, but it seems to make the changes appear
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ if (favDialog != null) {
+ favDialog.refresh();
+ }
+ }
+ }
+
+ }
+
+ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+
+ mapView.post(new Runnable() {
+ public void run() {
+ // updateEnabledOverlays(); TODO Fix whatever this did?
+ mapView.invalidate();
+ }
+ });
+
+ return true;
+ }
+
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case VIEW_DIALOG_ID:
+ ViewDialog viewDialog = new ViewDialog(instance);
+ viewDialog.setOnItemClickListener(this);
+ return viewDialog;
+ case FAVOURITE_DIALOG_ID:
+ favDialog = new FavouriteDialog(instance);
+ favDialog.setOnItemClickListener(this);
+ favDialog.setOnItemLongClickListener(this);
+ return favDialog;
+
+ }
+ return null;
+ }
+
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Log.i(TAG, "OnItemClick pos " + position + " id " + id);
+
+ String poiId = favDialog.adapter.getItemStringId(position);
+
+ Log.i(TAG, "POI " + poiId + " selected");
+
+ POI poi = null;
+
+ if (poiId != null) {
+ Log.i(TAG, "Got id " + poiId);
+ try {
+ poi = getHelper().getBuildingDao().queryForId(poiId);
+ if (poi == null) {
+ poi = getHelper().getBusStopDao().queryForId(poiId);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ if (poi == null) {
+ Log.e(TAG, "Could not find poi " + poiId + " in onActivityResult");
+ } else {
+ if (myLocationOverlay != null) {
+ myLocationOverlay.disableFollowLocation();
+ }
+ mapController.setZoom(20);
+ mapController.setCenter(poi.point);
+
+ favDialog.dismiss();
+
+ }
+ } else {
+ Log.i(TAG, "Got null poi id");
+
+ // mapController.setZoom(15);
+ // mapController.setCenter(new GeoPoint(50935551, -1393488));
+ }
+
+ }
+
+ /**
+ * Long click on a item in the favourites menu
+ */
+ public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+
+ Log.i(TAG, "OnItemClick pos " + position + " id " + id);
+
+ String poiId = favDialog.adapter.getItemStringId(position);
+
+ Log.i(TAG, "POI " + poiId + " selected");
+
+ POI poi = null;
+
+ if (poiId != null) {
+ Log.i(TAG, "Got id " + poiId);
+ try {
+ poi = getHelper().getBuildingDao().queryForId(poiId);
+ if (poi == null) {
+ poi = getHelper().getBusStopDao().queryForId(poiId);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ if (poi == null) {
+ Log.e(TAG, "Could not find poi " + poiId + " in onActivityResult");
+ } else {
+ if (poi.type == POI.BUS_STOP) {
+ BusStop busStop = (BusStop) poi;
+
+ Log.i(TAG, "Pressed " + busStop.id);
+
+ Intent i = new Intent(this, BusTimeActivity.class);
+ i.putExtra("busStopID", busStop.id);
+ i.putExtra("busStopName", busStop.description);
+ startActivityForResult(i, 0);
+
+ return true;
+
+ } else {
+
+ myLocationOverlay.disableFollowLocation();
+ mapController.setZoom(20);
+ mapController.setCenter(poi.point);
+
+ favDialog.dismiss();
+ favDialog = null;
+ }
+ }
+ } else {
+ Log.i(TAG, "Got null poi id");
+
+ // mapController.setZoom(15);
+ // mapController.setCenter(new GeoPoint(50935551, -1393488));
+ }
+
+ return true;
+ }
+
+ private class OverlayRankComparator implements Comparator<Overlay> {
+ private final SharedPreferences prefs;
+
+ OverlayRankComparator(SharedPreferences prefs) {
+ this.prefs = prefs;
+ }
+
+ public int compare(Overlay arg0, Overlay arg1) {
+ return getRank(arg1) - getRank(arg0);
+ }
+
+ private final int getRank(Overlay arg0) { // TODO: Dont hardcode the rank values
+ if (arg0 == scaleBarOverlay) {
+ return prefs.getInt("mScaleBarOverlay", 1);
+ } else if (arg0 == myLocationOverlay) {
+ return prefs.getInt("myLocationOverlay", 0);
+ } else if (arg0 == busStopOverlay) {
+ return prefs.getInt("busStopOverlay", 2);
+ } else if (arg0 == residentialBuildingOverlay) {
+ return prefs.getInt("residentialBuildingOverlay", 4);
+ } else if (arg0 == nonResidentialBuildingOverlay) {
+ return prefs.getInt("nonResidentialBuildingOverlay", 3);
+ } else if (siteOverlays != null && siteOverlays.values().contains(arg0)) {
+ return prefs.getInt("siteOverlays", 6);
+ } else if (routeOverlays != null && routeOverlays.values().contains(arg0)) {
+ return prefs.getInt("routeOverlays", 5);
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ /**
+ * Handles all changes in preferences
+ */
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ Log.v(TAG, "Got shared prefs changed event for key " + key);
+
+ if (key.equals("GPSEnabled")) {
+ final SharedPreferences activityPrefs = getPreferences(0);
+
+ if (activityPrefs.getBoolean("Other:Compass", false) && prefs.getBoolean("GPSEnabled", false)) {
+ myLocationOverlay.enableMyLocation();
+ } else {
+ myLocationOverlay.disableMyLocation();
+ }
+ } else if (key.equals("liveBusTimesEnabled")) {
+ // Noting to do here atm
+ } else if (key.contains("Bus Stops")) {
+ busStopOverlay.setRoutes(0, prefs.getBoolean("Bus Stops:U1", false));
+ busStopOverlay.setRoutes(1, prefs.getBoolean("Bus Stops:U1N", false));
+ busStopOverlay.setRoutes(2, prefs.getBoolean("Bus Stops:U2", false));
+ busStopOverlay.setRoutes(3, prefs.getBoolean("Bus Stops:U6", false));
+ busStopOverlay.setRoutes(4, prefs.getBoolean("Bus Stops:U9", false));
+ } else if (key.contains("Bus Routes")) {
+ for (BusRoute route : routeOverlays.keySet()) {
+ Log.v(TAG, route.code + " " + key.split(":")[1]);
+ if (route.code.equals(key.split(":")[1])) {
+ routeOverlays.get(route).setEnabled(prefs.getBoolean(key, false));
+ if (route.code.equals("U1")) {
+ overlays.get("Bus Routes:" + route.code + "E").setEnabled(prefs.getBoolean(key, false));
+ }
+ }
+ }
+ } else if (key.contains("Buildings")) {
+ if (key.equals("Buildings:Non-Residential")) {
+ nonResidentialBuildingOverlay.setEnabled(prefs.getBoolean(key, false));
+ } else if (key.equals("Buildings:Residential")) {
+ residentialBuildingOverlay.setEnabled(prefs.getBoolean(key, false));
+ } else {
+ Log.e(TAG, "Wierd building preferences key " + key);
+ }
+ } else if (key.contains("Site Outlines")) {
+ for (Site site : siteOverlays.keySet()) {
+ if (site.name.equals(key.split(":")[1])) {
+ siteOverlays.get(site).setEnabled(prefs.getBoolean(key, false));
+ }
+ }
+ } else if (key.contains("Other")) {
+ if (key.contains("Scale Bar")) {
+ scaleBarOverlay.setEnabled(prefs.getBoolean("Other:Scale Bar", false));
+ } else if (key.contains("Compass")) {
+ if (prefs.getBoolean("Other:Compass", false)) {
+ myLocationOverlay.enableCompass();
+ } else {
+ myLocationOverlay.disableCompass();
+ }
+ } else if (key.contains("Other:My Location")) {
+ final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ if (prefs.getBoolean("Other:Compass", false) && sharedPrefs.getBoolean("GPSEnabled", false)) {
+ myLocationOverlay.enableMyLocation();
+ } else {
+ myLocationOverlay.disableMyLocation();
+ }
+ } else {
+ Log.e(TAG, "Unhandled preference key " + key);
+ }
+ } else {
+ Log.e(TAG, "Unhandled preference key " + key);
+ }
+ }
+
+ class ViewDialog extends Dialog implements OnChildClickListener {
+
+ private final ExpandableListView epView;
+
+ private static final String TAG = "ViewDialog";
+
+ private final MyExpandableListAdapter mAdapter;
+
+ private OnChildClickListener listener;
+
+ public ViewDialog(Context context) {
+ super(context);
+
+ setContentView(R.layout.view_dialog);
+ setTitle("Select the map elements to display");
+
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
+ lp.copyFrom(this.getWindow().getAttributes());
+ lp.width = WindowManager.LayoutParams.FILL_PARENT;
+ lp.height = WindowManager.LayoutParams.FILL_PARENT;
+
+ this.getWindow().setAttributes(lp);
+
+ epView = (ExpandableListView) findViewById(R.id.view_list);
+ mAdapter = new MyExpandableListAdapter(context);
+ epView.setAdapter(mAdapter);
+ epView.setOnChildClickListener(this);
+
+ }
+
+ public void setOnItemClickListener(OnChildClickListener onChildClickListener) {
+ Log.i(TAG, "Listener set for dialog");
+ listener = onChildClickListener;
+ }
+
+ class MyExpandableListAdapter extends BaseExpandableListAdapter {
+
+ private LayoutInflater inflater;
+
+ private static final String TAG = "MyExpandableListAdapter";
+
+ // Bus Stops
+ // |_ U1
+ // |_ U1N
+ // |_ U2
+ // |_ U6
+ // |_ U9
+ // Bus Routes
+ // |_ U1
+ // |_ U1N
+ // |_ U2
+ // |_ U6
+ // |_ U9
+ // Buildings
+ // |_ Residential
+ // |_ Non-Residential
+ // Site Outlines
+ // |_ Highfield Campus
+ // |_ Boldrewood Campus
+ // |_ Avenue Campus
+ // |_ Winchester School of Art
+ // |_ The University of Southampton Science Park
+ // |_ National Oceanography Centre Campus
+ // |_ Boat House
+ // |_ Southampton General Hospital
+ // |_ Royal South Hants Hospital
+ // |_ Belgrave Industrial Site
+ // |_ Highfield Hall
+ // |_ Glen Eyre Hall
+ // |_ South Hill Hall
+ // |_ Chamberlain Hall
+ // |_ Hartley Grove
+ // |_ Bencraft Hall
+ // |_ Connaught Hall
+ // |_ Montefiore Hall
+ // |_ Stoneham Hall
+ // |_ Erasmus Park
+ // Other
+ // |_ Scale Bar
+ // |_ Compass
+ // |_ My Location
+
+ MyExpandableListAdapter(Context context) {
+ inflater = LayoutInflater.from(context);
+ }
+
+ public Object getChild(int groupPosition, int childPosition) {
+ if (groupPosition == 0 || groupPosition == 1) {
+ return busRoutes[childPosition];
+ } else if (groupPosition == 2) {
+ return buildingTypes[childPosition];
+ } else if (groupPosition == 3) {
+ return siteNames[childPosition];
+ } else if (groupPosition == 4) {
+ return other[childPosition];
+ } else {
+ Log.e(TAG, "Unrecognised groupPosition " + groupPosition);
+ return null;
+ }
+ }
+
+ public long getChildId(int groupPosition, int childPosition) {
+ return groupPosition * 50 + childPosition;
+ }
+
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
+ View v = null;
+ if (convertView != null)
+ v = convertView;
+ else
+ v = inflater.inflate(R.layout.view_child_row, parent, false);
+ String c = (String) getChild(groupPosition, childPosition);
+ TextView childName = (TextView) v.findViewById(R.id.childname);
+ if (childName != null)
+ childName.setText(c);
+ CheckBox cb = (CheckBox) v.findViewById(R.id.check1);
+ cb.setClickable(false);
+ cb.setFocusable(false);
+ SharedPreferences activityPrefs = getPreferences(0);
+
+ if (groupPosition == 0 || groupPosition == 1) {
+ cb.setChecked(activityPrefs.getBoolean(groupHeadings[groupPosition] + ":" + busRoutes[childPosition], true));
+ } else if (groupPosition == 2) {
+ cb.setChecked(activityPrefs.getBoolean(groupHeadings[groupPosition] + ":" + buildingTypes[childPosition], true));
+ } else if (groupPosition == 3) {
+ cb.setChecked(activityPrefs.getBoolean(groupHeadings[groupPosition] + ":" + siteNames[childPosition], true));
+ } else if (groupPosition == 4) {
+ cb.setChecked(activityPrefs.getBoolean(groupHeadings[groupPosition] + ":" + other[childPosition], true));
+ }
+ return v;
+ }
+
+ public int getChildrenCount(int groupPosition) {
+ if (groupPosition == 0 || groupPosition == 1) {
+ return busRoutes.length;
+ } else if (groupPosition == 2) {
+ return buildingTypes.length;
+ } else if (groupPosition == 3) {
+ return siteNames.length;
+ } else if (groupPosition == 4) {
+ return other.length;
+ }
+ return 0;
+ }
+
+ public Object getGroup(int groupPosition) {
+ return groupHeadings[groupPosition];
+ }
+
+ public int getGroupCount() {
+ return groupHeadings.length;
+ }
+
+ public long getGroupId(int groupPosition) {
+ return groupPosition * 5;
+ }
+
+ public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
+ View v = null;
+ if (convertView != null)
+ v = convertView;
+ else
+ v = inflater.inflate(R.layout.view_group_row, parent, false);
+ String gt = (String) getGroup(groupPosition);
+ TextView colorGroup = (TextView) v.findViewById(R.id.childname);
+ if (gt != null)
+ colorGroup.setText(gt);
+ return v;
+ }
+
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return true;
+ }
+
+ }
+
+ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+ Log.i(TAG, "Got view dialog click at " + groupPosition + ":" + childPosition);
+
+ SharedPreferences activityPrefs = getPreferences(0);
+
+ Editor editor = activityPrefs.edit();
+
+ CheckBox cb = (CheckBox) v.findViewById(R.id.check1);
+
+ if (groupPosition == 0 || groupPosition == 1) {
+ Log.i(TAG, "Setting value of " + groupHeadings[groupPosition] + ":" + busRoutes[childPosition] + " to " + !cb.isChecked());
+ editor.putBoolean(groupHeadings[groupPosition] + ":" + busRoutes[childPosition], !cb.isChecked());
+
+ } else if (groupPosition == 2) {
+ Log.i(TAG, "Setting value of " + groupHeadings[groupPosition] + ":" + buildingTypes[childPosition] + " to " + !cb.isChecked());
+ editor.putBoolean(groupHeadings[groupPosition] + ":" + buildingTypes[childPosition], !cb.isChecked());
+
+ } else if (groupPosition == 3) {
+ Log.i(TAG, "Setting value of " + groupHeadings[groupPosition] + ":" + siteNames[childPosition] + " to " + !cb.isChecked());
+ editor.putBoolean(groupHeadings[groupPosition] + ":" + siteNames[childPosition], !cb.isChecked());
+
+ } else if (groupPosition == 4) {
+ Log.i(TAG, "Setting value of " + groupHeadings[groupPosition] + ":" + other[childPosition] + " to " + !cb.isChecked());
+ editor.putBoolean(groupHeadings[groupPosition] + ":" + other[childPosition], !cb.isChecked());
+ }
+
+ editor.commit();
+
+ mAdapter.notifyDataSetInvalidated();
+
+ listener.onChildClick(parent, v, groupPosition, childPosition, id);
+
+ return true;
+ }
+
+ }
+}
diff --git a/src/net/cbaines/suma/Stop.java b/src/net/cbaines/suma/Stop.java
new file mode 100644
index 0000000..6e6bd39
--- /dev/null
+++ b/src/net/cbaines/suma/Stop.java
@@ -0,0 +1,78 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.util.Date;
+
+import android.text.format.DateUtils;
+
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "stops")
+public class Stop {
+
+ @DatabaseField(generatedId = true)
+ int id;
+
+ @DatabaseField(canBeNull = false)
+ String name;
+
+ @DatabaseField(canBeNull = false, foreign = true)
+ BusStop destStop;
+
+ @DatabaseField(canBeNull = true, foreign = true)
+ Bus bus;
+
+ @DatabaseField(canBeNull = false, foreign = true)
+ BusStop busStop;
+
+ @DatabaseField(canBeNull = false)
+ Date arivalTime;
+
+ @DatabaseField(canBeNull = false)
+ Date timeOfFetch;
+
+ Stop() {
+
+ }
+
+ Stop(String name, BusStop busStop, BusStop dest, Bus bus, Date arivalTime, Date timeOfFetch) {
+ this.name = name;
+ this.busStop = busStop;
+ this.destStop = dest;
+ this.bus = bus;
+ this.arivalTime = arivalTime;
+ this.timeOfFetch = timeOfFetch;
+ }
+
+ Stop(String name, BusStop busStop, BusStop dest, Date arivalTime, Date timeOfFetch) {
+ this(name, busStop, dest, null, arivalTime, timeOfFetch);
+ }
+
+ public String getTimeToArival() {
+
+ if (arivalTime.getTime() - System.currentTimeMillis() <= 60000) {
+ return "Due";
+ } else {
+ return (String) DateUtils.getRelativeTimeSpanString(arivalTime.getTime(), System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS);
+ }
+ }
+}
diff --git a/src/net/cbaines/suma/StopView.java b/src/net/cbaines/suma/StopView.java
new file mode 100644
index 0000000..9e58eb4
--- /dev/null
+++ b/src/net/cbaines/suma/StopView.java
@@ -0,0 +1,98 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.sql.SQLException;
+
+import android.content.Context;
+import android.view.Gravity;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.j256.ormlite.android.apptools.OpenHelperManager;
+import com.j256.ormlite.dao.Dao;
+
+public class StopView extends LinearLayout implements OnClickListener {
+
+ // private final ImageView icon;
+
+ // private static final String TAG = "StopView";
+
+ private final TextView name;
+ private final TextView time;
+ private String onClickMessage = "";
+ private final Context context;
+
+ public StopView(Context context, Stop stop) {
+ super(context);
+
+ this.context = context;
+
+ this.setOrientation(HORIZONTAL);
+
+ name = new TextView(context);
+ name.setTextSize(22f);
+
+ time = new TextView(context);
+ time.setTextSize(22f);
+ time.setGravity(Gravity.RIGHT);
+
+ setStop(stop);
+
+ addView(name, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ addView(time, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
+ }
+
+ public void setStop(Stop stop) {
+
+ // Log.i(TAG, "Time of arival " + stop.arivalTime);
+
+ name.setText(stop.name);
+ time.setText(stop.getTimeToArival());
+
+ DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
+
+ try {
+ Dao<Bus, Integer> busDao = helper.getBusDao();
+
+ busDao.refresh(stop.bus);
+
+ if (stop.bus != null) {
+ onClickMessage = "Bus " + stop.bus.toString();
+ } else {
+ onClickMessage = "Unidentified bus";
+ }
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ this.setOnClickListener(this);
+ }
+
+ public void onClick(View v) {
+ Toast.makeText(context, onClickMessage, Toast.LENGTH_SHORT).show();
+
+ }
+
+}
diff --git a/src/net/cbaines/suma/StringDistanceComparator.java b/src/net/cbaines/suma/StringDistanceComparator.java
new file mode 100644
index 0000000..0d19f53
--- /dev/null
+++ b/src/net/cbaines/suma/StringDistanceComparator.java
@@ -0,0 +1,132 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.util.Comparator;
+
+public class StringDistanceComparator implements Comparator<POI> {
+ private String userString;
+
+ // private static final String TAG = "StringDistanceComparator";
+
+ public StringDistanceComparator(String userString) {
+ super();
+ this.userString = userString;
+ }
+
+ public int compare(POI poi1, POI poi2) {
+ int distTo1 = LD(userString, poi1.toString());
+ // Log.i(TAG, "Comparing " + userString + " and " + poi1.toString() + " got dist " + distTo1);
+ int distTo2 = LD(userString, poi2.toString());
+ // Log.i(TAG, "Comparing " + userString + " and " + poi2.toString() + " got dist " + distTo2);
+ return distTo1 - distTo2;
+ }
+
+ // Below is public domain code from http://www.merriampark.com/ld.htm
+
+ // ****************************
+ // Get minimum of three values
+ // ****************************
+
+ private int Minimum(int a, int b, int c) {
+ int mi;
+
+ mi = a;
+ if (b < mi) {
+ mi = b;
+ }
+ if (c < mi) {
+ mi = c;
+ }
+ return mi;
+
+ }
+
+ // *****************************
+ // Compute Levenshtein distance
+ // *****************************
+
+ public int LD(String s, String t) {
+ int d[][]; // matrix
+ int n; // length of s
+ int m; // length of t
+ int i; // iterates through s
+ int j; // iterates through t
+ char s_i; // ith character of s
+ char t_j; // jth character of t
+ int cost; // cost
+
+ // Step 1
+
+ n = s.length();
+ m = t.length();
+ if (n == 0) {
+ return m;
+ }
+ if (m == 0) {
+ return n;
+ }
+ d = new int[n + 1][m + 1];
+
+ // Step 2
+
+ for (i = 0; i <= n; i++) {
+ d[i][0] = i;
+ }
+
+ for (j = 0; j <= m; j++) {
+ d[0][j] = j;
+ }
+
+ // Step 3
+
+ for (i = 1; i <= n; i++) {
+
+ s_i = s.charAt(i - 1);
+
+ // Step 4
+
+ for (j = 1; j <= m; j++) {
+
+ t_j = t.charAt(j - 1);
+
+ // Step 5
+
+ if (s_i == t_j) {
+ cost = 0;
+ } else {
+ cost = 1;
+ }
+
+ // Step 6
+
+ d[i][j] = Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
+
+ }
+
+ }
+
+ // Step 7
+
+ return d[n][m];
+
+ }
+
+}
diff --git a/src/net/cbaines/suma/Timetable.java b/src/net/cbaines/suma/Timetable.java
new file mode 100644
index 0000000..466bdfe
--- /dev/null
+++ b/src/net/cbaines/suma/Timetable.java
@@ -0,0 +1,31 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.util.ArrayList;
+
+public class Timetable extends ArrayList<Stop> {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -9021303378059511643L;
+
+}
diff --git a/src/net/cbaines/suma/TimetableAdapter.java b/src/net/cbaines/suma/TimetableAdapter.java
new file mode 100644
index 0000000..8326856
--- /dev/null
+++ b/src/net/cbaines/suma/TimetableAdapter.java
@@ -0,0 +1,60 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+public class TimetableAdapter extends BaseAdapter {
+
+ private final Context context;
+ private final Timetable timetable;
+
+ public TimetableAdapter(Context context, Timetable timetable) {
+ this.context = context;
+ this.timetable = timetable;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ StopView stopView;
+ if (convertView == null) {
+ stopView = new StopView(context, timetable.get(position));
+ } else {
+ stopView = (StopView) convertView;
+ stopView.setStop(timetable.get(position));
+ }
+
+ return stopView;
+ }
+
+ public int getCount() {
+ return timetable.size();
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+}
diff --git a/src/net/cbaines/suma/Util.java b/src/net/cbaines/suma/Util.java
new file mode 100644
index 0000000..7efbcbf
--- /dev/null
+++ b/src/net/cbaines/suma/Util.java
@@ -0,0 +1,95 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import java.util.ArrayList;
+
+import org.osmdroid.util.GeoPoint;
+
+import android.location.Location;
+import android.util.Log;
+
+public class Util {
+
+ private static final String TAG = "Util";
+
+ public static GeoPoint csLatLongToGeoPoint(String lat, String lng) {
+ try {
+ double dLat = Double.valueOf(lat).doubleValue();
+ double dLng = Double.valueOf(lng).doubleValue();
+ int iLat = (int) (dLat * 1e6);
+ int iLng = (int) (dLng * 1e6);
+ return new GeoPoint(iLat, iLng);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Error formating " + lat + " " + lng, e);
+ throw e;
+ }
+ }
+
+ public static GeoPoint ssLatLongToGeoPoint(String lat, String lng) {
+ try {
+
+ double dLat = Double.valueOf(lat).doubleValue();
+ double dLng = Double.valueOf(lng).doubleValue();
+ int iLat = (int) (dLat * 1e6);
+ int iLng = (int) (dLng * 1e6);
+ return new GeoPoint(iLat, iLng);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Error formating " + lat + " " + lng, e);
+ throw e;
+ }
+ }
+
+ public static Polygon csPolygonToPolygon(String str) {
+ // Log.i(TAG, "Getting poly from " + str);
+ ArrayList<GeoPoint> geoPoints = new ArrayList<GeoPoint>();
+
+ String[] latLongPoints = str.split(",");
+ for (int point = 0; point < latLongPoints.length; point++) {
+ // Log.i(TAG, "LatLong point " + point + " " + latLongPoints[point]);
+
+ String[] latLongs = latLongPoints[point].split(" ");
+ GeoPoint geoPoint = ssLatLongToGeoPoint(latLongs[1], latLongs[0]);
+ geoPoints.add(geoPoint);
+ }
+
+ return new Polygon(geoPoints.toArray(new GeoPoint[0]));
+ }
+
+ public static int doubleToIntE6(double dub) {
+ return (int) (dub * 1e6);
+ }
+
+ public static double E6IntToDouble(int integer) {
+ return (double) (integer / 1e6);
+ }
+
+ public static GeoPoint locationToGeoPoint(Location loc) {
+ return new GeoPoint(doubleToIntE6(loc.getLatitude()), doubleToIntE6(loc.getLongitude()));
+ }
+
+ public static Location geoPointToLocation(GeoPoint point) {
+ Location loc = new Location("");
+ loc.setLatitude(E6IntToDouble(point.getLatitudeE6()));
+ loc.setLongitude(E6IntToDouble(point.getLongitudeE6()));
+ return loc;
+ }
+
+}
diff --git a/src/net/cbaines/suma/Waypoint.java b/src/net/cbaines/suma/Waypoint.java
new file mode 100644
index 0000000..d56c05d
--- /dev/null
+++ b/src/net/cbaines/suma/Waypoint.java
@@ -0,0 +1,42 @@
+/*
+ * Southampton University Map App
+ * Copyright (C) 2011 Christopher Baines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package net.cbaines.suma;
+
+import org.osmdroid.util.GeoPoint;
+
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "routeWaypoints")
+public class Waypoint extends POI {
+
+ Waypoint() {
+ }
+
+ int sequence;
+
+ String route;
+
+ public Waypoint(int sequence, GeoPoint point) {
+ super(point.toDoubleString() + ":" + sequence, point);
+ this.type = POI.WAYPOINT;
+ this.sequence = sequence;
+ }
+
+}