Composant Delphi / Google Maps / OpenStreetMap / Leaflet  / Mappilary / Native Maps 100% Delphi 0% WebBrowser 0% Javascript

Layers

you are here :TECMap > Overlays

TECNativeLayer is the base class of the layers that allow you to react to the displayed area, and mouse actions.

TECNativeLayer = class
private
FObserver : TNativeMapObserver;
FShapes : TECShapes;
FMap : TNativeMapControl;

FOnShapeRightClick,
FOnShapeClick : TOnShapeMouseEvent;

FOnMouseClick,
FOnMouseMove : TNotifyEvent;

function getMinZoom : byte;
function getMaxZoom : byte;

procedure setMinZoom(value:byte);
procedure setMaxZoom(value:byte);

function getVisible : boolean;

protected

procedure doOnMapEndMove(sender : TObject); virtual;
procedure doOnShapeClick(sender : TObject); virtual;
procedure doOnShapeRightClick(sender : TObject); virtual;
procedure doOnMapMouseMove(sender : TObject); virtual;
procedure doOnMapMouseClick(sender : TObject); virtual;
procedure doOnMapHiResChange(sender : TObject); virtual;


public


procedure setVisible(const value:boolean); virtual;



constructor Create(_FMap:TnativeMapControl;const Name:string); virtual;
destructor Destroy; override;

property OnShapeClick : TOnShapeMouseEvent read FOnShapeClick write FOnShapeClick;
property OnShapeRightClick : TOnShapeMouseEvent read FOnShaperightClick write FOnShapeRightClick;

property OnMouseMove : TNotifyEvent read FOnMouseMove write FOnMouseMove;
property OnMouseClick : TNotifyEvent read FOnMouseClick write FOnMouseClick;


property Map : TNativeMapControl read FMap;
property Shapes : TECShapes read FShapes;
property Visible : boolean read getVisible write setVisible;

property MaxZoom : byte read getMaxZoom write setMaxZoom;
property MinZoom : byte read getMinZoom write setMinZoom;

end;



You can either plug into OnMapHiResChange or overload the doOnMapHiResChange(sender: TObject) procedure so that your layer adapts to change resolution

1

Panoramio

Google closed Panoramio November 4, 2016, the service is no longer functional

1

A Panoramio layer is integrated into TECNativeMap through the property PanoramioLayer

// Delphi map component ECMap

var ecNativeLineToRoute : TecNativeLineToRoute;
...
ecNativeLineToRoute := TecNativeLineToRoute.create;

// edit route
ecNativeLineToRoute.Line := map.shapes.Lines[0];

// end edit route
ecNativeLineToRoute.Line := nil;
...
ecNativeLineToRoute.free;




The event OnPanoramioClick(sender: TObject; const Item: TECShape; const ownerId, ownerName, PhotoId, PhotoDate, PhotoTitle, PhotoUrl, copyright: string) is raised when clicking a Panoramio item.

Fig. 1 Click sur un élément Panoramio

TECNativePlaceLayer


Allows you to automatically display the result of a search

To use this layer you must embed unit uecNativePlaceLayer or FMX.uecNativePlaceLayer depending on whether you use the VCL version or FireMonkey

1

Example: a layer that displays restaurants

// search Layer

FPlacesLayer := TECNativePlaceLayer.create(map,'PLACES_LAYER');
FPlacesLayer.OnPLaceClick := doOnPlaceClick;

FPlacesLayer.Visible := true;
FPlacesLayer.Search := 'node[amenity=restaurant]';
// standard image 32x32
FPlacesLayer.MarkerFilename := 'http://www.helpandweb.com/cake_32.png';
// lat,lng on center of image
FPlacesLayer.XAnchor := 16;
FPlacesLayer.YAnchor := 16;
// hi-res image 64*64
FPlacesLayer.MarkerHiResFilename := 'http://www.helpandweb.com/cake_64.png';
// lat,lng on center of image
FPlacesLayer.HiResXAnchor := 32;
FPlacesLayer.HiResYAnchor := 32;
...

// event click on place shape
procedure TForm1.doOnPlaceClick(sender : TECShape);
var
pResult : TECPlaceResult;
r,
n,
Content : string;
i : integer;
begin

// here Sender and Sender.Item are allway assigned, and Sender.Item is TECPlaceResult

pResult :=TECPlaceResult(Sender.item)


for i:=0 to pResult.CountResult-1 do
begin

n := pResult.NameResult[i];
r := pResult.Result[n];
if length(n)< 9 then
n := n+'<tab="65">';

content := content+'<b>'+n+'</b>: '+r+'<br>';

end;


if FPlacesLayer.Shapes.InfoWindows.Count=0 then
begin
FPlacesLayer.Shapes.InfoWindows.add(0,0,'');
FPlacesLayer.Shapes.InfoWindows[0].zindex := 100;
end;

FPlacesLayer.Shapes.InfoWindows[0].content := Content;
FPlacesLayer.Shapes.InfoWindows[0].SetPosition(Shape.Latitude,shape.Longitude);
FPlacesLayer.Shapes.InfoWindows[0].Visible := true;


end;


end;

Fig. 2 Click on an element TECNativePlaceLayer

By default the elements of layer are TECShapeMarker but you can change the type of TECShape by redefining TECNativePlaceLayer.doCreateShape(SearchResult : TECPlaceResult):TECShape;

XapiLayer

Instead, use the OverPassApi layer

2

XapiLayer uses TECNativePlaceLayer and is directly integrated with TECNativeMap.

The search is performed in the area displayed by your map, it is updated on each move

property Shapes:TECShapes

The group that contains the items, it's name is 'XAPI'

property Search : string


Research is done by doing a query on a server XAPI

You can find all the tags OSM using a syntax like 'node[key=value]'

// search bus stop
map.XapiLayer.Search := 'node[highway=bus_stop]';

For nodes you can use simplified syntax.

// search bus stop
map.XapiLayer.Search := 'highway=bus_stop';

For the key amenity you can simplify even more.

// search all restaurant, bar and café
map.XapiLayer.Search := 'restaurant|bar|cafe';

If you do not specify node in your query the areas will also be displayed.

3

To hide them define the style

map.Styles.addRule('#XAPI.polygone {visible:false}');

A point is added to the center of the surfaces, to not display it, add the style

map.Styles.addRule('#XAPI.marker {if:polyid>-1;visible:false}');

property Visible : boolean


show / hide layer

property MaxItem : integer


Maximum number of items

property OnClick : TOnShape

This event is raised when an item is clicked

property OnChange : TNotifyEvent

Raised after each request
map.XapiLayer.OnClick := doOnXapiClick;
map.XapiLayer.OnChange := doOnXapiChange;
...
procedure TForm1.doOnXapiChange(sender : TObject);
begin
//
end;

// event click on xapi shape
procedure TForm1.doOnXapiClick(sender : TECshape);
begin
//
end;

Use the styles to decorate your items

Selector := '#'+map.XapiLayer.Shapes.Name+ '.marker.amenity';

map.styles.addRule(Selector+':restaurant' +
'{graphic:base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAaBAMAAABI' +
'sxEJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJQTFRFAAAA////AAAAAAA'
+ 'AAAAAAAAA/h6U3wAAAAV0Uk5TAAAQgL++EJOXAAAAOElEQVQY02MIFQ0MFWRUCXVigLBcQ0OgrNDQUH'
+ 'JYQIDOMg0NDYawBIFC2FgCSCxBerFMg0Es02AAP34wMx8/aIAAAAAASUVORK5CYII=;visible:true;');

map.styles.addRule(Selector+':bar' +
'{graphic:base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAzklEQVRIx+2WUQ3'
+ 'FIAxFK2ES8HANVMIkIGUOkICESUDCJCABCdtPSQgJC2UjeXlZk3402e1ZoRSIGgZgA3AqfSOtAYgDoK'
+ 'iFmCxWaDLMaEAsoqDQBNGsGlDeHyexnbJPAHwpKuIe9zSwDFzFPR6egM4P9HMgX3YQgDSr67gQrsq51'
+ 'z8ZqqqSwHrOkhsZqguAo0iyS5weL1kD5qZUcjPNfXV1HPIThmaY9vr4QH8KknbPXbfMgtiqvSMA+1Zy'
+ 'lrNy9/SK8g0PVamc2NlTK98F1MyKB+QkmGEAAAAASUVORK5CYII=;visible:true;}');

map.styles.addRule(Selector+':cafe' +
'{graphic:base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOA'
+ 'AAAuUlEQVRIx2NgIACMjY0F0PgN+OTJBkCD9iMbCsT/cclTYkkCzGCoJfuB+D02eUosKQAZAjIM5nKQ'
+ 'JUBsgE2eEotQDIHyHXDJU2JRPyn8wQmgcfCfTPye1HghGw8/i4D4PBrbgVYWYcMGtLAoAakUmQ8VW0/'
+ 'TOALyFXDGHZUtEqCXRbCy8DzNLAKlNqTMn0ATi0AVI5LYflol7/1I7Pk4a18q5Zv3BKsPKpUMCvQogh'
+ 'RGS2+aW0SzGhYAB5lDXBZ7NtoAAAAASUVORK5CYII=;visible:true;}');

map.styles.addRule('#'+map.XapiLayer.Shapes.Name+ '.marker.highway:bus_stop {color:blue;styleicon:Flat;visible:true;}');
map.styles.addRule('#'+map.XapiLayer.Shapes.Name+ '.marker {scale:1;}');
map.styles.addRule('#'+map.XapiLayer.Shapes.Name+ '.marker:hover {scale:1.5;}');

Fig. 3 'restaurant|bar|cafe'

Fig. 4 'highway=bus_stop'

Way

With way[key = value] you can retrieve paths.

// find roads
map.XapiLayer.Search := 'way[highway=motorway|primary|secondary|tertiary|residential]';
// styles routes
map.styles.addRule('#' + map.XapiLayer.Shapes.Name +
'.line.highway:primary {zindex:9;weight:4;color:gradient(Red,Yellow,0.3);visible:true;}');
map.styles.addRule('#' + map.XapiLayer.Shapes.Name +
'.line.highway:secondary {zindex:8;weight:3;color:gradient(Red,Yellow,0.4);visible:true;}');

Fig. 5 Xapi Way

You can also find the junctions between routes.

map.XapiLayer.Junction := true;
map.XapiLayer.Search := 'way[highway=unclassified|road|motorway|trunk|primary|secondary|tertiary|residential]';

Fig. 6 Xapi Roads & Junction

Manual search

When layer is visible the search is synchronized with the visible area of your map.

To perform a search on any area you need to hide layer and use Bound to delimit the search box.

// sample, copie data in another group

map.XapiLayer.OnChange := XapiChange;
map.XapiLayer.visible := false;
map.XapiLayer.search := 'highway=bus_stop';
// ! call bound after set search !
map.XapiLayer.bound(43,0.7,44,0.8);
...
TForm.XapiChange(sender : TObject);
begin
// here xapilayer contain openstreetmap data
// copie in another group
map.group[copy_xapi'].ToTxt := map.XapiLayer.shapes.ToTxt;
end;

Mapillary

Only available for Delphi 10.x and higher!

1

Mapillary is a service of the same type as Google Street Map, it allows you to display photos at street level, the advantage is that you can enrich it yourself by recording your routes.

TECNativeMap only uses open source information from Mapillary, you need a key to use Mapillary services.

For this go to the site www.mapillary.com, connect, add your applications, you will then get a token which will serve as your access key.

To use mapillary you must incorporate the unit uecMappilary or FMX.uecMappilarydepending on whether you are using the VCL or FireMonkey

2

Use TECMapillaryLayer to display a Mapillary layer.

FMapillaryLayer := TECMapillaryLayer.Create(map);

FMapillaryLayer.OnClick := doOnMapillaryLayerClick;
FMapillaryLayer.OnTrafficSignClick := doOnMapillaryLayerTrafficSignClick;

FMapillaryLayer.OnBeginRequest := doBeginRequest;
FMapillaryLayer.OnendRequest := doEndRequest;

FMapillaryLayer.LocalCache := ExtractfilePath(ParamStr(0)) + 'cache';

FMapillaryLayer.Visible := true;

Fig. 7 Demo Mapillary

TECMapillaryLayer

function FindImageClose(const Lat, Lng: double; Distance: integer; var seq : TMapillarySequence; var PhotoIndex : integer ) : integer;

Find the nearest photo among those displayed in the layer, the search is local among the elements displayed on the map.

Lat,Lng indicates the starting point of the search

Distance indicates the maximum distance in meters from the search area

Seq will contain the sequence found or nil

PhotoIndex will contain the index of the picture in seq or -1

Returns the distance in meters between the search point and the photo, 0 if no photo

function SearchImageClose(const Lat,Lng:double; DistanceMeter : integer; ListSequenceImage : TListSequenceImage):integer;

Search all the images included in a radius of DistanceMeter meters, the search is in local

Lat,Lng indicates the starting point of the search

DistanceMeter indicates the maximum distance in meters of the search radius

ListSequenceImage will contain a list of TSequenceImage (a couple sequence, image index)

Returns the number of images found

See the demo MappilarySearchImages for a usage example

3

Fig. 8 DemoFiremonkeyMappilarySearchImages

procedure SearchBounds(NorthEastLatitude, NorthEastLongitude, SouthWestLatitude, SouthWestLongitude: double);

Run a manual search on the Mapillary servers to find the images of the area
property MinZoom : byte
Minimal zooming so that Mapillary queries are executed automatically depending on the visible area of your map, default zoom 15
function LoadMapillaryBitmap(const url: string; const FBitmap: TBitmap): boolean;
Load FBitmap with the url of an image

function DetectionsImage(const image_id:int64;const List:TListDataDetections):integer;

TDataDetections = record
id,
value,
create_at,
geometry : string;
end;

Fill the list with all the items detected in the image, returns the number of items

// search for elements contained in the image
L := TListDataDetections.Create;
try
n := FMapillaryLayer.DetectionsImage(SelectedSequence[SelectedImageIndex].Id,L);
Detections.Lines.BeginUpdate;

for i := 0 to n-1 do
Detections.Lines.Add(L[i].value);

Detections.Lines.EndUpdate;
finally
L.Free;
end;

property AccessToken: string ;

MANDATORY your key to use Mapillary services
property LocalCache: string ;
Local cache directory, the one on your map is used when creating

property Tiles: TMapillaryTiles

List of TMapillaryTile currently in memory

a TMapillaryTile contains a property Sequences : TMapillarySequences which is a list of TMapillarySequence which itself is a list of TMapillaryImage

TMapillaryImage = class
property Compass_angle: int64 ;

property Lat: double ;
property Lng: double ;

property Sequence_id: string ;
property Organization_id: int64 ;
property Id: int64 ;

property Captured_at: TDateTime ;

property is_Pano: boolean ;

property Url256: string;
property Url1024: string;
property Url2048: string;
end;

there is also a property TrafficSign:TListTrafficSign which is a list of TTrafficSign

TTrafficSign = record
id : int64;
First_seen_at,
last_seen_at : TDateTime;
lat,lng : double;
value: string;
end;

procedure Clear;

Erase all Mapillary elements from your map

The data contained in the Tiles are not erased, so there will be no need to reconnect to the mapillary servers to display them again

4

procedure ClearAll;

Delete displayed items and data from Tiles

property Visible : boolean

Shows or hides the Mapillary layer

Visible acts on both images and signage

5

property TrafficSignVisible : boolean

Displays or hides signage

property MaxDayInCache : integer;
Lifetime of the data stored in the local cache, by default 30 days
property OnClick: TOnMapillaryLayerClick ;

Triggered when clicking on a mapillary image

// click on line or marker mapillary
procedure TForm.doOnMapillaryLayerClick(Layer : TECMapillaryLayer; item : TECShape;
MapillarySequence : TMapillarySequence; ImageIndex : integer);
var bmp:TBitmap;
begin
// show photo in a TImage
bmp := TBitmap.Create;
try
// load image 256*256
// also url1024 and url2048

if FMapillaryLayer.LoadMapillaryBitmap(MapillarySequence[ImageIndex].Url256,bmp) then
Image.Picture.Assign(bmp);

finally
bmp.Free;
end;

end;
property OnTrafficSignClick: TOnMapillaryLayerTrafficSignClick ;

Triggered when clicking on a traffic mapillary element

// click on marker mapillary traffic sign
procedure TForm30.doOnMapillaryLayerTrafficSignClick(layer: TECMapillaryLayer; item: TECShape;
ListTrafficSign: TListTrafficSign; TrafficSignIndex: integer) ;
begin
FMapillaryLayer.OpenWindow(item.Latitude,item.Longitude,
'<h4>'+ListTrafficSign[TrafficSignIndex].value+ '</h4><br>'+
'<tab="10"><b>Id</b><tab="40"> : '+IntToStr(ListTrafficSign[TrafficSignIndex].id)+ '<br>'+
'<tab="10"><b>Lat</b><tab="40"> : '+DoubleToStrDigit(ListTrafficSign[TrafficSignIndex].lat, 5)+'<br>'+
'<tab="10"><b>Lng</b><tab="40"> : '+DoubleToStrDigit(ListTrafficSign[TrafficSignIndex].lng, 5),
250 // width=250
);
end;
property OnSequenceColor:TOnMapillaySequenceColor;

Allows you to assign a color to a sequence.

By default a unique color is assigned according to the sequence id, so a sequence will always have the same color.

6
FMappilaryLayer := TECMappilaryLayer.Create(map);
FMappilaryLayer.AccessToken := 'HERE-YOUR-TOKEN';

FMappilaryLayer.Visible := true;

property OnBeginRequest: TNotifyEvent

Event triggered just before launching a Mapillary request

property OnEndRequest: TNotifyEvent

Event triggered just after the return of a Mapillary request
// fill a TComboBox with all the sequences
procedure TForm.doEndRequest(sender: TObject);
var i,j:integer;

begin

ComboSequences.Items.BeginUpdate;
ComboSequences.items.clear;

for i := 0 to FMapillaryLayer.Tiles.Count-1 do
for j :=0 to FMapillaryLayer.Tiles[i].Sequences.Count-1 do
// store name and TMapillarySequence
ComboSequences.items.addObject(FMapillaryLayer.Tiles[i].Sequences[j].Sequence_id,FMapillaryLayer.Tiles[i].Sequences[j]);

ComboSequences.Items.EndUpdate;

end;

Heatmap

A heat map is used to represent the intensity of data for geographic points.

Fig. 9 Heatmap layer

TECHeatmapLayer is the class that allows to manage this type of layer.

constructor Create(_FMap: TECNativeMap);
// create heatmap layer
HeatmapLayer := TECHeatmapLayer.Create(map);

procedure Clear;

Erase all of the data



procedure Add(const Latitude, Longitude: double; const value: double = 1);

Add a geographical point and assign it a value, you can make several additions to the same point.



procedure Remove(const latitude, longitude: double; const Value: double);

Delete the Value element if it exists at these coordinates
procedure Update;

After adding the points, call Update to refresh the layer


property AutomaticUpdate: boolean
By default false, switch to true if you want the HeatMap to be automatically updated each time you change it.
property Palette: THeatPalette

Palette allows you to manage the colors that are used to create the gradient


HeatmapLayer.Palette.Clear;

// addColor(Red,Green,Blue,Value)
// Red,Green, and Blue byte 0..255
// value double 0..1

// this is the default palette, you can also use Palette.reset for recreate it

HeatmapLayer.Palette.AddColor(0,0,0,0); // black for value=0
HeatmapLayer.Palette.AddColor(0,0,255,0.1);// blue for value=0.1
HeatmapLayer.Palette.AddColor(0,255,255,0.25); // cyan for value=0.25
HeatmapLayer.Palette.AddColor(0,255,0,0.5); // green for value=0.5
HeatmapLayer.Palette.AddColor(255,255,0,0.75); // yellow for value=0.75
HeatmapLayer.Palette.AddColor(255,0,0,1); // red for value=1

property Visible: boolean ;

property PointIsDisc : boolean;

Determines if the point is displayed in the form of a disc, otherwise it's a square

Fig. 10 Style of the point


Property Radius:integer;

The point size

property Opacity : byte;

Change the opacity of the layer (0 to 100)

property MinZoom: byte ;

Minimum zoom layer to display



property MaxZoom: byte ;

Maximum zoom layer to display



property GroupZIndex: integer ;

ZIndex of the group containing all of the heatmaps, is displayed in ascending order of the ZIndex



property ZIndex: integer ;

ZIndex of the layer compared to the other heatmap

property OnUpdate: TNotifyEvent;

Event fired when the heat map was generated


Weather Layer

By using the services of OpenWeathermap.org you will be able to see overlay layers owPrecipitation, owSnow, owClouds, owPressure, owTemp, owWind

map.OpenWeatherTilesLayer.Key := 'your api key';
// see pressure
map.OpenWeatherTilesLayer.Add(owPressure) ;
// see precipitation
map.OpenWeatherTilesLayer.Add(owPrecipitation) ;
// remove pressure
map.OpenWeatherTilesLayer.remove(owPressure) ;

TomTom Traffic Incidents

Unlike tomtom's incident tiles, this layer allows you to get information about incidents by hovering the mouse or by pressing your finger.

Fig. 11 TomTom Traffic Incidents

// get your key at https://developer.tomtom.com/user/register
map.TomTom.Key := 'your api key';
map.TomTom.Incident.Layer := true;

TECTomTomIncident

property CategoryLabel : TStringList

This list contains the type of incident, the title is included in the information heading.
You can use it to make a translation but make sure to respect the order and the number of elements

property CacheTime : int64

Time in milliseconds during which the information is kept in memory, by default 180000 (3mn)

property Layer : boolean

Activate / Deactivate the layer

property InfoStyle : TInfoWindowStyle

Style of infoWindow, default iwsRectangle

property FontColor : TColor

Text color, default black

property BorderColor : TColor

Border color, default to a light gray

property Break : integer

Spacing in pixels between paragraphs, default 7

property Tab : integer

Width in pixels of the first column, default 40

property TextDelay : string

Label 1st paragraph, default "delay" (use TextXXX fields for your translation)

property TextLength : string

Label 2nd paragraph, default "Length

property TextFrom : string

Label 3rd paragraph, default "From

property TextTo : string

Label 4th paragraph, default "To

property Width : integer

Width infoWindow, default 240

property YAnchor : integer

Vertical offset of the infoWindow, default -25

property OnClick : TOnShapeMouseEvent

Event triggered by a click on an incident.
map.TomTom.Incident.OnClick := doIncidentClick;
// show all properties
procedure TForm1.doIncidentClick(sender: TObject; const item: TECShape);
var Key, Value, content: string;
win: TECShapeInfoWindow;
begin
content := '';
if item.PropertiesFindFirst(Key, Value) then
begin
repeat
// if necessary line break
if content<>'' then content := content+'<br>';
// align the values to 110 pixels
Key := Key + '<tab=110>';
// Bold the keys
content := content + '<b>' + Key + '</b>: ' + Value ;
// continue as long as there are properties
until item.PropertiesFindNext(Key, Value);
end;

// create window if not exists
if map['info'].InfoWindows.count = 0 then
begin
win := map['info'].AddInfoWindow;
win.Width := 350;
end
else
win := map['info'].InfoWindows[0];

win.content := content;
win.SetPosition(map.MouseLatLng.Lat, map.MouseLatLng.lng);
win.Visible := true;
end;

Fig. 12 Incident OnClick

Styling the information

property Style : string

Contains the styles assigned to the lines.

By default as for tomtom tiles the colors are functions of the magnitude of delay

'#TOMTOM-INCIDENT.line{weight:8;bsize:2;hbcolor:light(black,128);bcolor:light(black,48);penStyle:dot;}';
'#TOMTOM-INCIDENT.line.magnitudeOfDelay:0 {color:#BFBFBF}';
'#TOMTOM-INCIDENT.line.magnitudeOfDelay:1 {color:#F58240}';
'#TOMTOM-INCIDENT.line.magnitudeOfDelay:2 {color:#EB4C13}';
'#TOMTOM-INCIDENT.line.magnitudeOfDelay:3 {color:#AB0000}';
'#TOMTOM-INCIDENT.line.magnitudeOfDelay:4 {color:#8B837D}';

The infoWindow has properties that will allow you to set a style in response

  • iconCategory : 0-14 index on the CategoryLabel list
  • delay : number of seconds
  • length : number of meters
// default style
map.Styles.addRule('#TOMTOM-INCIDENT.infowindow{bcolor:light(gray,128);color:white;fontcolor:black}');
// style if the wait is more than 5mn (delay>300)
map.Styles.addRule('#TOMTOM-INCIDENT.infowindow{if:delay>300;bcolor:dark(red,128);color:light(red,96);fontcolor:white}');

OverPassApi layer

This layer has the same utility as the XAPI layer but it uses OverPassApi which is a newer technology and should therefore be seen as the replacement for the XAPI layer.

The purpose is to extract specific data from OpenStreetMap located in the displayed area of your map, an automatic refresh takes place after each move.

If you define a local cache the searches will be saved there and will be available in offline mode.

7

Fig. 13 Demo OverPassLayer

procedure Amenity(value: string;const Data:TSetOSMData=[odNode,odWay]);

Display amenities equal to Value.
Data indicates if we are looking for the nodes and/or the Ways

procedure Amenity(values: array of string;const Data:TSetOSMData=[odNode,odWay]; const Op: TBinaryFilterOSM = bfOr);

Search for multiple amenities at once

Amenity() procedures are a simplification of Tag() procedures, with a tag_key implicitly equal to "amenity"

8

procedure Tag(const key, value: string;const Data:TSetOSMData=[odNode,odWay]);

Show Key tag equal to Value.
Data indicates whether to search for Nodes and/or Ways.

procedure Tag(const key:string;const values: array of string;const Data:TSetOSMData=[odNode,odWay]; const Op: TBinaryFilterOSM = bfAnd);

Search for Key tags with multiple Values
op=bfAnd return tags only if they have all values
op=bfOr selects the tag if it has at least one Value

procedure Tag(const tags: array of string;const Data:TSetOSMData=[odNode,odWay]; const Op: TBinaryFilterOSM = bfAnd);

Search for a array of Key=Value

property Query: string

You define your request freely, the bbox and the out will be added automatically
// search Way 'highway'='residential
map.OverPassApi.layer.Tag('highway','residential',[odWay]);
// search Way 'highway'='residential' OR 'highway'='primary'
map.OverPassApi.layer.Tag('highway',['residential','primary'],[odWay],bfOr);
//search Way width highway=residential AND name='Park Avenue'
map.OverPassApi.layer.Tag(['highway','residential','name','Park Avenue'],[odWay],bfAnd);
// search Nodes and Way amenity=parking
map.OverPassApi.layer.Amenity('parking']);
// search only Nodes amenity=restautant or amenity=parking
map.OverPassApi.layer.Amenity(['restaurant','parking',[odNode]);
// search nodes and ways amenity=parking
map.OverPassApi.layer.Query := 'nw[amenity=parking]';

property Group: TECShapes

Groupe which will be used to display the elements of the OverPassApi layer

property Visible: boolean

Activate/deactivate the layer

property TimeOut: integer

Maximum duration of the request in seconds, by default 60, set to 0 to not indicate a timeout

property OnBeginQuery: TNotifyEvent

Event triggered just before the query is launched

property OnEndQuery: TNotifyEvent

Event triggered when the request is returned

property OnClick: TOnShapeMouseEvent

Event triggered by a click on a layer element

property OnData:TECOnOverPassLayerData

Event triggered when OpenStreetMap XML data is available
map.OverPassApi.Layer.OnBeginQuery := doOnBeginQuery;
map.OverPassApi.Layer.OnEndQuery := doOnEndQuery;
map.OverPassApi.Layer.OnClick := doOnClick;
map.OverPassApi.Layer.OnData := doOnData;
...
// fired when xml data ready
procedure TForm9.doOnData(const XmlValue:string);
begin
XmlData.Lines.Text := XmlValue;
end;
// fired when click on ovepassapi layer item
procedure TForm9.doOnClick(sender: TObject; const item: TECShape);
var Key, Value, content: string;
win: TECShapeInfoWindow;
begin
content := '';

if item.PropertiesFindFirst(Key, Value) then
begin
repeat
// if necessary line break
if content<>'' then content := content+'<br>';
// align the values to 100 pixels
Key := Key + '<tab=100>';
// Bold the keys
content := content + '<b>' + Key + '</b>: ' + Value ;
// continue as long as there are properties
until item.PropertiesFindNext(Key, Value);
end;

// create window if not exists
if map.OverPassApi.Layer.Group.InfoWindows.count = 0 then
begin
win := map.OverPassApi.Layer.Group.AddInfoWindow;
win.Width := 270;
end
else
win := map.OverPassApi.Layer.Group.InfoWindows[0];

win.content := content;
win.SetPosition(map.MouseLatLng.Lat, map.MouseLatLng.lng);
win.Visible := true;

end;

// start query
procedure TForm9.doOnBeginQuery(sender : TObject);
begin
QuerySearch.Visible := true;
end;
// end query
procedure TForm9.doOnEndQuery(sender : TObject);
begin
QuerySearch.Visible := false;
end;
go to page
Réalisé avec la version gratuite pour les particuliers d'Help&Web