Google Maps in Delphi with TMS WebGMaps: Adding custom routes
Embarcadero delivers controls to retrieve data from REST APIs with Delphi rather easily. Still, reading into these APIs takes time and you need even more time to work out all the oddities that arise not mentioned in the documentation. I presented a couple of examples on this very blog with the Pexels and Barcode components.
If you rather want to save some time the Google Maps component from TMS Software, available for both FireMonkey and VCL, might just be it. The component allows you to use the full API provided by Google all wrapped in a Delphi (actually also C++) component without having to think of the REST interface. Just use the component by interacting with its methods and properties and the appropriate interaction with the Maps API is handled by the component.
This week a new version was released that supports defining custom routes. Thus, implementing an application to trace a route or evaluate route options has become very easy. As always, new components also come with many non-visible enhancements. Earlier versions of the component (as also mentioned on this blog) needed a call to the Launch method in order to start the interaction with the map. This has become redundant in this version. The following implementation is no longer necessary when using Delphi 10.1 Berlin:
procedure TForm1.FormShow(Sender: TObject); begin WebGMaps1.Launch; end;
Before starting with the step-by-step instructions, let me mention that there is no Google API key needed. You may use the component “out of the box”, trial versions are available. Thus, you will be able to reproduce this description downloading the component here.
Installation is pretty straight forward as an installer is provided. We will start off by opening the sample project that shows the routing functionality that was added in the new version. You find the samples in the public documents folder named “Routing Demo” in the folder with the “WebGMaps Demos”:
Starting the demo as is, you are already able to add waypoints to the route by clicking on the map. Note that the component connects the waypoints using roads.
In order to show how easy it is to work with the component we will expand the functionality of the application. We will add the ability to move the map to a certain location and will also show the total distance of the route as well as all the waypoints. Realizing that functionality using the REST API manually is a lot of work.
The Google Maps API expects you to use coordinates, given by their latitude and longitude. However, the component pack also offers components to transfer an address into coordinates and vice versa. This component will allow us to move (or pan) the map to the location we desire.
Let’s drop some components on the form:
- Before starting to add the additional components for more functionality, add a TSplitter component in between the panel on the left and the map on the right.
- Drop a TWebGMapsGeocoding -component (Geocode). This component will handle the transfer from an address, provided as a string to geographical coordinates.
- Drop a TEdit (txtAddress) in the panel on the list that will provide the means to enter an adress. Also set its Anchor so that it expands to the right when moving the splitter.
- Drop a TButton (btPanTo) and label it “Pan to Address”. The button will launch the code to move the map to the address provided.
The form should look like this:
Now we will implement the geocoding of the address into the coordinates and move the map accordingly. However, we will only move the map if the address was able to be converted:
procedure TForm1.btPanToClick(Sender: TObject); begin Geocode.Address := txtLocation.Text; // move map if coordinated are determined if Geocode.LaunchGeocoding = TGeocodingResult.erOk then begin WebGMaps1.MapPanTo( Geocode.ResultLatitude, Geocode.ResultLongitude ); end; end;
First we assign the text from the TEdit to the Addess property of the geocoding component and start the process by invoking the method called LaunchGeocoding .
Mind that the geocoding returns a result that allows us to decide if we have a valid location or not. TGeocodingResult.erOK tells us that all went fine and we can move the map. We move the view by calling the method MapPanTo with the coordinates, which we get from the properties of the geocoding component.
Finally, we define a method that populates the listbox with data and also updates the label’s caption with the total distance of the route specified:
procedure TForm1.UpdateListbox; var i : Integer; item: TPathItem; begin lbPath.Items.BeginUpdate; try lbPath.Clear; for i := 0 to WebGMaps1.Routing.Path.Count-1 do begin item := WebGMaps1.Routing.Path.Items[i]; lbPath.AddItem( Format('Lat: %.4f Lon: %.4f', [ item.Latitude, item.Longitude ] ), item); end; finally lbPath.Items.EndUpdate; end; labelDistance.Caption := 'Distance: ' + IntToStr( WebGMaps1.Routing.Distance ); end;
Let’s have a look at a route from Signal Iduna Park in Dortmund to Dortmund University. Entering “Signal Iduna Park Dortmund” and clicking “Pan to Address” positions the map. The I add two more waypoint as I want to drive by certain waypoints as I know they are best to drive home after a game with well over 80.000 people in attendance:
Our very simple app is already able to interact with other applications as we can export the route as a GPX file. Of course, you also can load routes stored in GPX files.
You see, working with the component is really straight forward and there is no need to dive into the complicated REST API. The component abstracts from all of that and you can focus on the implementation of your features instead.