* load the libraries DO LOCFILE("here_loader.prg") * instantiate an overHere manager LOCAL oh AS overHere m.oh = CREATEOBJECT("overHere") m.oh.SetCredentials(YOUR-API-KEY-HERE)2. Get the coordinates of the addresses
* first, let's get some addresses from the NorthWind database SELECT * ; FROM (HOME(0) + "Samples\Northwind\customers") ; WHERE City == "London" AND Country == "UK" ; INTO CURSOR curCustomers CREATE CURSOR curWaypoints ; (WPId Varchar(20), ; Latitude Double (4), Longitude Double (4), ; Sequence Integer NULL DEFAULT NULL, ; Arrival Datetime NULL DEFAULT NULL, Departure Datetime NULL DEFAULT NULL) * and try to find their geo coordinates LOCAL GC AS oh_GeocodeSearch m.GC = m.oh.SetResource("GeocodeSearch") * we start by locating the Heathrow Airport m.GC.SearchText.Set("UK Heathrow Airport") IF !ISNULL(m.GC.GetLocation(.T.)) AND m.GC.Location.Views.Count > 0 INSERT INTO curWaypoints (WPId, Latitude, Longitude) ; VALUES ('HEATHROW0', ; m.GC.Location.Views(1).Results(1).Location.NavigationPosition.Latitude.Get(), ; m.GC.Location.Views(1).Results(1).Location.NavigationPosition.Longitude.Get()) INSERT INTO curWaypoints (WPId, Latitude, Longitude) ; VALUES ('HEATHROW1', ; m.GC.Location.Views(1).Results(1).Location.NavigationPosition.Latitude.Get(), ; m.GC.Location.Views(1).Results(1).Location.NavigationPosition.Longitude.Get()) ELSE ? "Couldn't locate starting point, aborting..." RETURN ENDIF * and now the customers' addresses location SELECT curCustomers SCAN m.GC.SearchText.Set(TEXTMERGE("<<TRIM(curCustomers.city)>> <<TRIM(curCustomers.address)>>")) IF !ISNULL(m.GC.GetLocation(.T.)) AND m.GC.Location.Views.Count > 0 INSERT INTO curWaypoints (WPId, Latitude, Longitude) ; VALUES (curCustomers.customerid, ; m.GC.Location.Views(1).Results(1).Location.NavigationPosition.Latitude.Get(), ; m.GC.Location.Views(1).Results(1).Location.NavigationPosition.Longitude.Get()) ELSE ? "Not found:", TRIM(curCustomers.address) ENDIF ENDSCAN3. Find the visit sequence
* by now, we have the starting point (Heathrow Airport) and the known addresses of our customers in London * let's find the best visit sequence LOCAL FS AS oh_FindSequence LOCAL WP AS oh_WaypointWithIdType LOCAL WPF AS oh_FindWaypointInfoType m.FS = m.oh.SetResource("FindSequence") * we'll go by car m.FS.Mode.Set("Type", "fastest") m.FS.Mode.Set("Transport", "car") m.FS.Mode.Set("TrafficMode", "enabled") m.FS.ImproveFor.Set("time") SELECT curWaypoints GO TOP * where do we start m.FS.Start.Set(curWaypoints.wpid , curWaypoints.latitude, curWaypoints.longitude) * we also want to go back to Heathrow, after our visits SKIP m.FS.End.Set(curWaypoints.wpid, curWaypoints.latitude, curWaypoints.longitude) * when we'll start (tomorrow, at 09:00) m.FS.Departure.Set(DTOT(DATE() + 1) + 9 * 3600) SKIP SCAN REST * add all the customers addresses m.WP = CREATEOBJECT("oh_WaypointWithIdType") m.WP.Set(curWaypoints.wpid, curWaypoints.latitude, curWaypoints.longitude) * let's assume our visits will take 30 minutes each m.WP.ServiceTime.Set(30 * 60) m.FS.Destinations.Add(m.WP) ENDSCAN * find the sequence m.FS.Find(.T.)4. Get a route for the sequence
* we have a sequence, now we need a route for it LOCAL CR AS oh_CalculateRoute LOCAL GC AS oh_GeoWaypointParameterType m.CR = m.oh.SetResource("CalculateRoute") * copy the settings from the find sequence resource * to get consistent directions m.CR.Mode.Set("Type", m.FS.Mode.Get()) m.CR.Mode.Set("Transport", m.FS.Mode.TransportMode.Get()) m.CR.Mode.Set("TrafficMode", m.FS.Mode.TrafficMode.Get()) m.CR.Departure.Set(m.FS.Departure.Get()) * use the waypoints in the sequence to define the route * contrary to the find sequence resource, calculate route will respect * the waypoints in the order they are added FOR EACH m.WPF IN m.FS.Sequence.Results(1).Waypoints * register the sequence of waypoints for browsing, later UPDATE curWaypoints ; SET Sequence = m.WPF.Sequence.Get(), ; Arrival = m.WPF.EstimatedArrival.Get(), ; Departure = m.WPF.EstimatedDeparture.Get() ; WHERE WPId == m.WPF.Id.Get() * add the waypoint to the route we want to calculate m.GC = CREATEOBJECT("oh_GeoWaypointParameterType") m.GC.Set(,,m.WPF.Latitude.Get(), m.WPF.Longitude.Get(),,,m.WPF.Id.Get()) m.CR.Waypoints.Add(m.GC) ENDFOR * just some typical settings m.CR.Representation.Set("display") m.CR.ManeuverAttrib.Parse("po,le,tt,bb") m.CR.InstructionFormat.Set("text") m.CR.Calculate(.T.)5. Display the route
* the route is calculated, by now * although we have lots of details in the calculated route * we just want to draw a map of it LOCAL RM AS oh_RouteMap m.RM = m.oh.SetResource("RouteMap") LOCAL Route AS oh_MapRouteMarkerGroupType LOCAL Pos AS oh_GeoCoordinateType LOCAL RouteShape AS oh_GeoPolylineType m.Route = CREATEOBJECT("oh_MapRouteMarkerGroupType") * get the shape of the route from the response m.Route.RouteCoords.Parse(m.CR.Route.Routes.Item(1).Shape.ToString()) * set it, it's almost ready to display m.RM.Routes.Add(m.Route) * back to our waypoints, we want to display markers along the route FOR EACH m.WPF IN m.FS.Sequence.Results(1).Waypoints m.POI = CREATEOBJECT("oh_PointOfInterestType") m.POI.Set(m.WPF.Latitude.Get(), m.WPF.Longitude.Get(), ; "ffB0B0", "004040", 10, m.WPF.Sequence.ToString() + " " + m.WPF.Id.Get()) m.RM.PointsOfInterest.Add(m.POI) ENDFOR * get the map of the route m.RM.Request() IF TYPE("_Screen.oh") == "U" _Screen.AddObject("oh", "Image") _Screen.oh.Visible = .T. ENDIF * and display it in the VFP screen _Screen.oh.PictureVal = m.RM.GetImage() * browse through the unordered and ordered sequence of points * (the map will be left behind) SELECT curWaypoints GO TOP BROWSE NOWAIT LAST SELECT * FROM curWaypoints ORDER BY Sequence INTO CURSOR curOrderedWaypoints SELECT curOrderedWaypoints GO TOP BROWSE NOWAIT LAST