API Keys
TECNativeMap uses OpenStreetMap.
If you want to use these services of PTV or TomTom or MapBox you must register on their site to obtain a user key .
Offline mode
If you specify a directory in the LocalCache property, all your geolocation data will be cached and can be reused in offline mode.
Address format
You benefit from the services of geolocation via the property GeoLocalise de type TECGelocalise
The Address property gives you the address of the center of the map, it is of type string and is accessible in read/write
TECGeolocalise uses the services of OpenStreetMap and OpenMapQuest
You can also use ArcGis through functionsfunction TECGeolocalise.ArcGisFind(const data:string;var Lat,Lng:double):boolean;
Geolocalisation
To obtain the address of a specific you have the function GetAddressFromLatLng(const dLatitude,dLongitude:double):string;
You can get the various parts of the address by using the property TECGeolocalise.ReverseResults:TStringList
// now ReverseResults contains tags in nominatim <addressparts>
// see https://nominatim.org/release-docs/latest/api/Reverse/
country := map.Geolocalise.ReverseResults.values['country'];
road := map.Geolocalise.ReverseResults.values['road'];
postcode:= map.Geolocalise.ReverseResults.values['postcode'];
...
You can get the coordinates of an address with the function GetLatLngFromAddress(const sAddress:string;var dLatitude,dLongitude:double):boolean;
By assigning a value to the property Address you will change the position of the center of your map to match to the address
Places
TECGeolocalise allows you to search specific locations in a data area, for example to find restaurants within a radius of 500 metres.
It is Overpass-api that uses data from OpenStreetMap which is used
The property TECGeolocalise.Places.XapiServer allows you to use another server Xapi than MapQuest
// use overpass-api.de
map.GeoLocalise.Places.XapiServer := 'http://www.overpass-api.de/api/xapi?';
Launch a search, tags contains the query
adr :=
map.GetAddressFromLatLng(Latitude,Longitude) ;
// now ReverseResults contains
tags in nominatim <addressparts>
// see
https://nominatim.org/release-docs/latest/api/Reverse/
country :=
map.Geolocalise.ReverseResults.values['country'];
road :=
map.Geolocalise.ReverseResults.values['road'];
postcode:=
map.Geolocalise.ReverseResults.values['postcode'];
...
When the search is complete, the Geolocalise.OnSearch event is raised
Each launch of Search clears the results of a previous search
1Property read-only that returns a string indicating the status of the search, 'OK' if all went well
The status is available in the event GeoLocalise.OnSearch
TECPlacesResults
This class manages the list of the results returned by Search
TECPlaceResult
Class handling a result corresponding to a search
DemonativeLocalise
the DemoNativeLocalise program shows you how to manage Places
Geofences
Geofence is a virtual area that triggers an alert when you enter or exit.
Adds a circular area defined by its center point and RADIUS in meters.
Adds a polygonal area defined by an array containing the various points
Adds a polygonal area defined by a polygon
Adds a area defined by a line
Import / export geofences in text format
By default, when you Save the map in text format the geofences are saved and can be recharged
TECBaseGeofence
Maximum activation time (milliseconds) (default 0 infinite)
map.geofences.geofence[0].ActiveDuration := 3000;
TECCirclegeoFence
property RadiusMeter : integerTECLineGeoFence
property MargingMeter : integerÉvenements Geofences
To respond connect you on OnEnterGeofence and OnLeaveGeofence of TECNativeMap events.
map.OnEnterGeofence := mapEnterGeofence;
map.OnLeaveGeofence := mapLeaveGeofence;
...
procedure TForm1.mapEnterGeofence(sender: TObject; const Geofence: TECBaseGeofence; const item: TECShape);
begin
caption := 'item '+inttostr(item.id)+' enter in '+Geofence.Name;
end;
procedure TForm1.mapLeaveGeofence(sender: TObject; const Geofence: TECBaseGeofence; const item: TECShape);
begin
caption := 'item '+inttostr(item.id)+' leave '+Geofence.Name;
end;
The detection is done when a shape is moved, the test is performed on location (latitude and longitude) not on the actual surface of the object.
Boundary
Boundary allows you to obtain the polygons, polylines and data of an area just by indicating a geographical point or an address..
function Address(value:string; const limit:integer=1):integerFind the geometry of the address
Limit sets the maximum number of results
Returns the number of elements
poly:TECShapePolygone;
...
for i := 0 to map.Boundary.Address('Paris') - 1 do
begin
poly := nil;
line := nil;
if (map.Boundary.Items[i] is TECShapePolygone) then
poly := TECShapePolygone(map.Boundary.Items[i])
else if (map.Boundary.Items[i] is TECShapeLine) then
line := TECShapeLine(map.Boundary.Items[i]);
if assigned(poly) then
poly.Hint := poly.PropertyValue['display_name'];
else if assigned(line) then
line.Hint := line.PropertyValue['display_name'];
end;
map.Boundary.FitBounds;
AddLineFromAddress et AddPolygoneFromAddress utilisent en interne Address avec la limite maximale de résultats
1poly : TECShapePolygone;
first_item:integer;
...
// use default group
first_item := map.shapes.lines.count;
line := map.AddLineFromAddress('avenue des champs-élysées, paris');
// line is the last find,total is (line.indexof - first_item + 1)
if assigned(line) then
line.fitBounds;
map['polyAddress'].clear;
poly := map.AddPolygoneFromAddress('parking, tarbes','polyAddress');
if assigned(poly) then
map['polyAddress'].fitBounds;
function Administrative(const lat,lng:double;Level:integer=0):integer;
Finds the administrative area whose level is crossed (from 2 to 10), indicating 0 the level is determined according to the zoom
Returns the number of elements
map.boundary.Administrative(43.2332,0.0736); // Level in function of zoom
Allows to control the administrative level according to the zoom level
Default :
Zoom 0 - 4 = Level 2
Zoom 5 - 8 = Level 4
Zoom 9 - 11 = Level 6
Zoom 12 - 24 = Level 8
map.Boundary.AdminLevelFromZoom := '0-8=4,9-24=8';
// Pass an empty string to reset to default values
map.Boundary.AdminLevelFromZoom := '';
Generic function that allows you to define the area to be found.
Returns the number of elements
map.boundary.Filter(43.2332,0.0736,'"admin_level"="8"');
Zooms in on the map to display the set of items contained in Items
begin
poly := nil;
line := nil;
if (map.Boundary.Items[i] is TECShapePolygone) then
poly := TECShapePolygone(map.Boundary.Items[i])
else
if (map.Boundary.Items[i] is TECShapeLine) then
line := TECShapeLine(map.Boundary.Items[i]) ;
if assigned(poly) then
begin
Poly.FillColor := GetHashColor(Address.Text);
Poly.FillOpacity := 10;
Poly.Opacity := 100;
Poly.PenStyle := psDash;
Poly.BorderColor := Poly.FillColor;
Poly.BorderSize := 4;
end;
if assigned(line) then
begin
line.Color := GetHashColor(Address.Text);
line.Opacity := 100;
line.PenStyle := psDash;
line.weight := 4;
end;
end;
map.Boundary.fitBounds;
property Id:int64;
ID OSM of the found area
property Tags:TStringlist
Contains the list of tags OSM of the area, in the form key = value
property OverPassUrl:string;
OverPass is used to find the area ( by default https://overpass-api.de/api/interpreter )
For the polygon from the id of the area, it connects to polygons.openstreetmap.fr
To change that assign a procedure to GetPolygoneFromID
map.Boudary.GetPolygoneFromID := myGetPoygonFromId;
procedure TForm.myGetPoygonFromId(const id:int64;var JSON:string);
begin
// here retourne yours polygons in json format
JSON := ...
end;
See DemoNativeBoundaryArea for a demo
GeoHash
Geohash is a public domain geocoding system invented by Gustavo Niemeyer,which encodes a geographic location into a short string of letters and digits..
More information on wikipedia.
procedure TNativeMapControl.GeoHash.Decode(const geohash: string; var latitude, longitude: double);
map.geoHash.Decode('9xj5smj4w40m',lat,lng);
function TNativeMapControl.GeoHash.Encode(const latitude, longitude: double;const precision:Integer=12): string
s := map.geoHash.encode(map.latitude,map.longitude);
function TNativeMapControl.GeoHash.CardinalPoints(const geohash:string):TCardinalGeoHash;
var cgh : TCardinalGeoHash;
cgh := map.geoHash.CardinalPoints('9xj5smj4w40m');
cgh.North;
cgh.NorthEast;
cgh.East;
cgh.SouthEast;
cgh.South;
cgh.SouthWest;
cgh.West;
cgh.NorthWest;
procedure TNativeMapControl.GeoHash.MoveTo(const geohash:string);
Open Location Code
Open Location Code (OLC) is a system of geocoding identifying an area anywhere on the Earth. It was developed at Google's Zurich Office.
More information on wikipedia.
function TNativeMapControl.OpenLocationCode.Encode(const latitude,longitude : Double;const codeLength:Integer=10):string;
olc := map.OpenLocationCode.encode(lat,lng);
// Provides an extra precision code, approximately 2x3 meters.
olc := map.OpenLocationCode.encode(lat,lng,11);
function TNativeMapControl.OpenLocationCode.Decode(const code:string):TecOLC_CODEAREA;
olcArea := map.OpenLocationCode.Decode('8FM263JF+PM');
olcArea.latitudeLo;
olcArea.longitudeLo;
olcArea.latitudeHi;
olcArea.longitudeHi;
olcArea.latitudeCenter;
olcArea.longitudeCenter;
olcArea.codeLength;
// zoom to the area
map.fitbounds(olcArea)
// draw polygone
map.AddPolygone(olcArea);
procedure TNativeMapControl.OpenLocationCode.MoveTo(const OpenLocationCode:string);
In the uecOpenLocationCode.pas unit you will find a class to use OpenLocationCode regardless of TECNativeMap, this is my translation of the openlocationcode.js of Google
2QTH Locator
Maidenhead Locator System, (a.k.a. QTH Locator and IARU Locator) is a geocode system used by amateur radio operators to succinctly describe their geographic coordinates.
The encoding uses a series of pairs of letters and numbers. The first sign of a pair concerns the longitude, the second the latitude.
QTH:string;
...
map.QTHLocatorToLatlng('JN03AF85UX',lat,lng);
// return locator with 5 pairs
QTH := map.LatLngToQTHLocator(Map.MouseLatLng.Lat,FMap.MouseLatLng.Lng);
Altitude
The elements have an Altitude property that returns an altitude in meters.
An internet connection is required, if you use a cache, the altitude will be written there.
SIf you move the element a new query will be performed the next time Altitude is accessed, otherwise the old value is returned.
By default it is opentopodata that is used with the mapzen dataset, 2 other services can be used instead.
map.GeoLocalise.ApiAltitude := altOpenElevation;
// For mapquest you must provide your own key in map.MapQuestKey = 'your_key'.
map.GeoLocalise.ApiAltitude := altMapQuest;
You can also define your own service.
map.GeoLocalise.ApiAltitude := altCustom;
// get 1 point
map.GeoLocalise.OnGetAltitude := your_getAltitude;
// get n points
map.GeoLocalise.OnGetAltitudes := your_getAltitudes;
procedure your_getAltitude(const LocalCache:string;const Latitude,Longitude:double;var altitude:double);
begin
// put result in altitude
end;
procedure your_getAltitudes(const LocalCache:string;const sLatLngs: string;var altitudes:string);
begin
// sLatLngs = lat1,lng1,lat2,lng2...
// put results in altitudes ( '310,120,158' )
end;