Saturday 26 January 2019

TravelTimeCalculator: Adding Markers With Custom Image

The last step (for now) is to add markers that represents the quickest/shortest transport modes between the center of the map and some other coordinates.

I'll start with adding a marker at the center of the map (target). I'll round the coordinates to the closest three-decimal number (36.2123321->36.212). The marker will be updated every time the map moves.

There will also be an arbitrary number of markers representing the existing directions from the current origin coordinate. Those markers will appear and disappear, depending on the current location.

A snippet will show the best distance/duration and an icon will show the best mode of transport

Single Marker

It's easier to implement the single marker, so I'll start with that one for now.
The first step is to simply add the marker at the center of the map. After changing the icon of the marker is now changed in two steps:
Step 1: Add an icon to the resource file

Step2: Let the marker object point to the icon resource 


To make the marker update when the user moves the map, I made a small change in the onCameraMove listener in the map object.
The code rounds the coordinates to the closest 3rd decimal. 
The purpose of this is to reduce the number of possible coordinates. Otherwise, I'd have zillions of coordinates in the database, many of them only feet apart.

Saturday 19 January 2019

TravelTimeCalculator: Tying it All Together

TravelTimeHandler is now working in the sense that it collects directions from Google Directions (or casched from the internal SQLite database) and select the quickest option.

Implementation
I started with skeleton code that indicated what it was supposed to do using printouts to the logs.


The stubbed method. I'll replace the
console print statements with actual
code later.
After having the overall structure in place, I implemented the needed methods:

  • scanDirectionsForTap is activated when the user taps the map. It starts with a query to the database for any directions between the center of the map and the tapped location. If no results are found, it queries Google Directions for bicycling, driving, transit and walking.
  • getShortestDirectionFromDb queries the database for the shortest duration (or distance) between two points. It returns the value and an integer representing the mode.
  • saveDirectionsToDb saves the directions to the database
  • clearMarkers will clear the markers from the map (stub). I'll call this method when the map is moved.
  • addMarkers will add a marker to the map (stub)
  • getDirectionsFromUrl queries Google Directions for distance and duration for a couple of coordinates and a mode of transport. The response is handled in the over-ridden method onResponse. onResponse adds the result to the database. After that, it will query the database for the shortest distance/duration using getShortestDirectionFromDb.
  • readDirectionsFromJson extracts the relevant data from the JSON response from Google Directions.

Since the database handles only integers for the coordinates, I'll multiply the coordinates by 1000 and round them to integers when querying the database. 

The output from some queries is:
Initially, the app had no direction data for the coordinates.
After the query, the database was populated with the data.

Context 
One issue that I saw was applicationContext. When having code that uses context in another file than the mainActivity.java file, the app can't find it. The solution was to get the app context explicitly:


Remaining Work
I want to visualize the results with markers. I'll add one marker in the middle that represents the current location.

When the user taps on the map, I'll add a corresponding marker on the map. The marker will have a color or symbol that indicates the quickest transport mode (driving, transit, walking or bicycling).

When the user moves the map, the existing markers are cleared. The app should look for existing directions in the database and add corresponding markers automatically.

Saturday 12 January 2019

TravelTimeCalculator: Selecting Coordinates to Scan for Directions

I'll simplify the selection of destination coordinate to scan for. Instead of having the app selecting some coordinates around the center, I'll let the user select the coordinates by tapping on the map.

The work flow will be like:
  • User re-zooms and pans the map to a new origin:
  • Clear existing markers (clearMarkers)
  • The app searches for any existing directions starting or ending at the coordinates (getDirectionsFromDb)
    • If found, it adds corresponding markers (addMarkers).
  • If the user taps the map,
    • If coordinates are not found in database, (getDirectionsFromDb is null)
      • Send Google Directions requests, (getDirectionsFromUrl)
      • Save response to database (saveDirectionsToDb)
      • Add marker to map
    • If coordinates are found, add marker to map
Step 1: Add a OnMapClickListener
I followed the instructions regarding detecting a tap on map from the official documentation. As soon as the map was installed, it crashed. The crash was my mistake, since I added the code in "onCreate". After adding the code to "onMapReady", it worked.

Step 2: Create a new class, TravelTimeHandler that handles the requests and decides whether to send a Directions query or query the database. It shall also add data to the database.

I moved the methods getDirections and readDirections to that class.

Step 3: Define what methods new methods to use.

  • readDirectionsFromJson
  • getDirectionsFromUrl
  • getDirectionsFromDb
  • saveDirectionsToDb
  • clearMarkers
  • drawMarker

Step 4: Implement those methods.
I'll cover this step in the next blog post

Saturday 5 January 2019

2018 in Retrospect

The last year, I had quite some progress on my projects. A normal week, I spend two hours on coding, two hours on learning and two hours on blogging.

TrafficControl (C++/Qt):
  • I added locks for tracks in order to avoid trains to travel in opposite directions on the same track. I also added red and green circles to visualize the lock status of the tracks.
  • Further, I added an icon to the executable 
  • The Python script that parses the KML map to a network in TrafficControl was modified: Now, it ignores hidden tracks and the tracks/stations doesn't need to be in any specific folder.
  • Improving the model for acceleration of trains
  • User Interface Improvements: I added system load and simulated time to the user interface.
    • Adding buttons for the controls 
    • Adding menus and toolbars
    • Adding a Help menu that points to some Help sections on this blog.
  • NetworkDesigner is a new tool that helps the user design a network
StockReader (Was: C, now: Python):
  • I re-implemented the web scraper in Python. Now, it has only 24 lines of code, including a check of the robots.txt policy.
TravelTimeCalculator (Android/Java):
HouseReader (Python)
I've also started another blog that will discuss society-related issues.

In 2019, I'll make TravelTimeCalculator demo-able. After that, I'll continue with TrafficControl, adding passenger handling.