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

Layers

Vous êtes ici :TECMap > Overlays

TECNativeLayer est la classe de base des layers qui vous permettent de réagir en fonction de la zone affichée et des actions de la souris.

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;



TECNativePlaceLayer

Vous permet d'afficher automatiquement le résultat d'une recherche

Pour utiliser ce layer vous devez incorporer l'unité uecNativePlaceLayer ou FMX.uecNativePlaceLayer selon que vous utilisiez la version VCL ou FireMonkey

1

Exemple : un layer qui affiche les 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. 1 Click sur un élément TECNativePlaceLayer

Par défaut les éléments du layer sont des TECShapeMarker mais vous pouvez changer le type de TECShape en redéfinissant TECNativePlaceLayer.doCreateShape(SearchResult : TECPlaceResult):TECShape;

XapiLayer

Préférez plutôt le layer OverPassApi

1

XapiLayer utilise TECNativePlaceLayer et est directement intégrer dans TECNativeMap pour une utilisation simplifié.

La recherche s'effectue dans la zone affichée par votre carte et est mise à jour à chaque déplacement

property Shapes:TECShapes

Le groupe qui contient les éléments affichés, il est nommé 'XAPI'

property Search : string


La recherche s'effectue en faisant une requête sur un serveur XAPI

Vous pouvez rechercher tous les tags OSM en utilisant une syntaxe du type 'node[key=value]'

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

Pour les nodes vous pouvez utiliser une syntaxe simplifiée.

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

Pour les clef amenity vous pouvez simplifier encore plus.

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

Si vous ne spécifiez pas node dans votre requête les surfaces vont aussi être affichées.

2

Pour les cacher définissez le style

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

Un point est rajouté au centre des surfaces, pour ne pas l'afficher, rajoutez le style

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

property Visible : boolean


Affiche / cache le layer

property MaxItem : integer


Nombre d'éléments maximum

property OnClick : TOnShape

Cet événement est déclenché lors d'un click sur un item du layer

property OnChange : TNotifyEvent

Déclenché après chaque requête
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;

Utilisez les styles pour habiller vos éléments

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. 2 'restaurant|bar|cafe'

Fig. 3 'highway=bus_stop'

Way

Avec une syntaxe du type way[key=value] pour pouvez extraire des chemins.

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. 4 Xapi Way

Vous pouvez aussi trouver les jonctions entres les routes.

Fig. 5 Xapi Roads & Junction

Recherche manuelle

Lorsque le layer est visible la recherche est synchronisée avec la zone visible de votre carte.

Pour pouvoir effectuer une recherche sur n'importe quelle zone vous devez cacher le layer et utiliser Bound pour délimiter la zone de recherche.


Mapillary

Uniquement disponible pour Delphi 10.x et supérieur !

1

Mapillary est un service du même type que Google Street Map, il permet d'afficher des photos au niveau des rues, l'avantage est que vous pouvez vous-même l'enrichir en enregistrant vos parcours.

TECNativeMap se contente d'utiliser les informations en libre accès au près de Mapillary, vous devez obtenir une clef pour utiliser les service de Mapillary.

Pour cela allez sur le site www.mapillary.com, connectez-vous, ajoutez vos applications, vous obtiendrez alors un token qui vous servira de clef.

Pour utiliser mapillary vous devez incorporer l'unité uecMappilary ou FMX.uecMappilary selon que vous utilisiez la version VCL ou FireMonkey

2

Utilisez TECMapillaryLayer pour incorporer un layer Mapillary.

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. 6 Demo Mapillary

TECMapillaryLayer

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

Trouver la photo la plus proche parmis celles affichées dans le layer, la recherche est en local.

Lat,Lng indique le point de départ de la recherche

Distance indique la distance maximale en mètres de la zone de recherche

Seq contiendra la séquence trouvée ou nil

PhotoIndex contiendra l'index de la photo dans seq ou -1

Retourne la distance en mètres entre le point de recherche et la photo, 0 si pas de photo

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

Recherche l'ensemble des images comprise dans un rayon de DistanceMeter metres, la recherche est en local

Lat,Lng indique le point de départ de la recherche

DistanceMeter indique la distance maximale en mètres du rayon de recherche

ListSequenceImage contiendra une liste de TSequenceImage (un couple sequence, image index)

Retourne le nombre d'images trouvées

Voyez la démo MappilarySearchImages pour un exemple d'utilisation

3

Fig. 7 DemoFiremonkeyMappilarySearchImages

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

Lance une requete manuelle sur les serveurs de Mapillary pour trouver les images de la zone
property MinZoom : byte
Zoom minimal pour que des requetes a Mapillary soient lancées automatiquement en fonction de la zone visible de votre carte, par défaut zoom 15
function LoadMapillaryBitmap(const url: string; const FBitmap: TBitmap): boolean;
Charge FBitmap avec l'url d'une image

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

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

Remplir la liste avec l'ensemble des éléments détectés dans l'image, retourne le nombre d'éléments

// 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 ;

OBLIGATOIRE votre clef pour utiliser les services de Mapillary
property LocalCache: string ;
Répertoire du cache local, celui de votre carte est utilisé lors de la création

property Tiles: TMapillaryTiles

Liste des TMapillaryTile actuellement en mémoires

une TMapillaryTile contient une property Sequences:TMapillarySequences qui est une liste de TMapillarySequence qui elle même est une liste de 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;

il y a aussi un property TrafficSign:TListTrafficSign qui est une liste de TTrafficSign

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

procedure Clear;

Efface tous les éléments Mapillary de votre carte

Les données contenues dans les Tiles ne sont pas effacées, il n'y aura donc pas besoin d'une reconnexion aux serveurs mapillary pour les réafficher

4

procedure ClearAll;

Effacer les éléments affichés et les données des Tiles

property Visible : boolean

Affiche ou cache le layer Mapillary

Visible agit a la fois sur les images et la signalisation

5

property TrafficSignVisible : boolean

Affiche ou cache la signalisation

property MaxDayInCache : integer;
Durée de vie des données stockées dans le cache local, par défaut 30 jours
property OnClick: TOnMapillaryLayerClick ;

Déclenché lors d'un click sur une image mapillary

// 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 ;

Déclenché lors d'un click sur un élément de traffic mapillary

// 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;

Permet d'attribuer une couleur à une séquence.

Par défaut une couleur unique est attribuée en fonction de la clef de la séquence, une séquence aura donc toujours la même couleur.

6

property OnBeginRequest: TNotifyEvent

Événement déclenché juste avant le lancement d'une requête Mapillary

property OnEndRequest: TNotifyEvent

Événement déclenché juste après le retour d'une requête Mapillary
// 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

Une carte thermique permet de représenter l'intensité des données pour des points géographiques.

Fig. 8 Heatmap layer

TECHeatmapLayer est la classe qui permet de gérer ce type de layer.

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

procedure Clear;

Effacer l'ensemble des données



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

Ajouter un point géographique et lui assigner une valeur, vous pouvez faire plusieurs ajouts sur un même point.


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

Supprimer l'élément Value s'il existe à ces coordonnées
procedure Update;

Après l'ajout des points, appelez Update pour actualiser le layer


property AutomaticUpdate: boolean
Par défaut false, basculez à true si vous souhaitez que la HeatMap soit automatiquement mise à jour à chaque modification

property Palette: THeatPalette

Palette permet de gérer les couleurs qui sont utilisées pour créer le dégradé


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;

Détermine si le point est affiché sous la forme d'un disque, sinon c'est un carré

Fig. 9 Style d'affiche des points


Property Radius:integer;

Taille du point


property Opacity : byte;

Change l'opacité du layer (de 0 à 100)


property MinZoom: byte ;

Zoom minimal pour que le layer s'affiche



property MaxZoom: byte ;

Zoom maximal pour que le layer s'affiche



property GroupZIndex: integer ;

Zindex du groupe contenant l'ensemble des heatmaps, l'affichage s'effectue dans l'ordre croissant des ZIndex



property ZIndex: integer ;

ZIndex du layer par rapport aux autres heatmap



property OnUpdate: TNotifyEvent;

Événement déclenché lorsque la carte thermique a été généré



Weather Layer

En utilisant les services d'OpenWeathermap.org vous pourrez superposer des 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

Contrairement aux tuiles incidents de tomtom, ce layer permet d'obtenir des informations sur les incidents lors du survol de la souris ou par une pression du doigt.

Fig. 10 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

Cette liste contient le type d'incident, l'intitulé est repris en titre des informations.
Vous pouvez l'utiliser pour effectuer une traduction mais veillez bien à respecter l'ordre et le nombre d'éléments.

property CacheTime : int64

Temps en millisecondes pendant lequel les informations sont gardées en mémoire, par défaut 180000 (3mn)

property Layer : boolean

Activer / Désactiver le layer

property InfoStyle : TInfoWindowStyle

Style de l'infoWindow, défaut iwsRectangle

property FontColor : TColor

Couleur du texte, défaut noir

property BorderColor : TColor

Couleur de la bordure, défaut un gris léger

property Break : integer

Intervale en pixels entre les paragraphes, défaut 7

property Tab : integer

Largeur en pixels de la première colonne, défaut 40

property TextDelay : string

Label 1er paragraphe, défaut "delay" (utilisez les champs TextXXX pour votre traduction)

property TextLength : string

Label 2ème paragraphe, défaut "Length"

property TextFrom : string

Label 3ème paragraphe, défaut "From"

property TextTo : string

Label 4ème paragraphe, défaut "To"

property Width : integer

Largeur infoWindow, défaut 240

property YAnchor : integer

Décalage vertical de l'infoWindow, défaut -25

property OnClick : TOnShapeMouseEvent

Événement déclenché par un click sur un 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. 11 Incident OnClick

Styler les informations

property Style : string

Contient les styles attribués aux lignes.

Par défaut comme pour les tuiles de TomTom les couleurs sont fonctions de l'amplitude du délai

'#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}';

L'infoWindow est dotée de propriétés qui vont vous permettre de définir un style en réaction

  • iconCategory : 0-14 index sur la liste CategoryLabel
  • delay : nombre de secondes
  • length : nombre de mètres
// 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}');

Layer OverPassApi

Ce layer a la même utilité que le layer XAPI mais il utilise OverPassApi qui est une technologie plus récente et doit donc être vu comme le remplaçant du layer XAPI.

Le but est d'extraire des données spécifique d'OpenStreetMap se trouvant dans la zone affichée de votre carte, une réactualisation automatique a lieu après chaque déplacement.

Si vous définissez un cache local les recherches y seront enregistrées et seront disponibles en mode hors-ligne.

7

Fig. 12 Demo OverPassLayer

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

Afficher les amenities égale à Value.
Data indique si l'on cherche les node et/ou les Way

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

Chercher plusieur amenities à la fois

les procedures Amenity() sont une simplification des procedures Tag(), avec un tag_key implicitement égal à "amenity"

8

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

Afficher les tag Key égal à Value.
Data indique si l'on cherche les Nodes et/ou les Ways.

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

Chercher les tags Key avec des multiples Values
op=bfAnd ne retourne les tags que s'ils ont toutes les values
op=bfOr sélection le tag s'il a au moins une Value

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

Chercher un ensemble de Key=Value

property Query: string

Vous définissez librement votre requête, la bbox et le out seront rajoutés automatiquement
// 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 qui servira pour afficher les éléments du layer OverPassApi

property Visible: boolean

Active/Désactive le layer

property TimeOut: integer

Durée maximale de la requête en secondes, par défaut 60, mettez à 0 pour ne pas indiquer de timeout

property OnBeginQuery: TNotifyEvent

Événement déclenché juste avant le lancement de la requête

property OnEndQuery: TNotifyEvent

Événement déclenché au retour de la requête

property OnClick: TOnShapeMouseEvent

Événement déclenché par un clic sur un élément du layer

property OnData:TECOnOverPassLayerData

Événement déclenché lorsque les données XML d'OpenStreetMap sont disponibles
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;

Bubble Layer

Un calque à bulles affiche des symboles (cercles ou autres formes) et éventuellement des labels. La taille et la couleur peuvent être contrôlées par des mesures, les labels par des propriétés. La position peut être spécifiée sous forme de lieu ou de valeurs de latitude et de longitude.

Fig. 13 Demo Bubble Layer

TECBubbleLayers

Gestionnaire de layers

function Add(const Name: string): TECBubbleLayer;
Ajoute un layer
procedure Delete(const Name: string);
procedure Delete(const index: integer);
Détruit un layer spécifié par son nom ou son index
procedure Clear;
Détruit tous les layers
function getLayers(const aList: TStrings): integer;
Rempli aList avec la liste des layers et retourne leur nombre
property Color: TColor
Couleur par défaut pour les éléments
property UseColorPalette: boolean
Si true la palette du layer est utilisée, la couleur des éléments dépendra de leur taille
property Count: integer
Nombre de layers
property MaxItemSize: integer
property MinItemSize: integer
la taille des éléments sera échelonnée entre MinItemSize et MaxItemSize pixels
property Layer[const index: string]: TECBubbleLayer
property List[const index: integer]: TECBubbleLayer
Retourne un layer en fonction de son nom ou de son index
property Opacity: byte
Opacité des éléments
property shape: TPOIShape
Forme des éléments (poiEllipse, poiStar, poiRect, poiTriangle, poiOwnerDraw,
poiHexagon, poiDiamond, poiText, poiArrow, poiArrowHead, poiCross,
poiDiagCross, poiDirectionSign)
property OnChange: TNotifyEvent
Déclenché lors de l'ajout ou de la suppression d'un layer
property OnEditBubble: TECOnEditBubble
Déclenché après la création d'un élément, cela permet de modifier ses propriétés (forme, couleur,...)
property OnClick: TOnShapeMouseEvent
Click sur un élément
property OnRightClick: TOnShapeMouseEvent
Click droit sur un élément

Vous retrouvez la plus part de ses propriétés au niveau du layer, cela vous permet de les centraliser.

9
Map.BubbleLayers.Color := clGreen;
Map.BubbleLayers.OnEditBubble := doOnEditBubble;
Map.BubbleLayers.OnClick := doOnClick;
Map.BubbleLayers.OnRightClick := doOnRightClick;
Map.BubbleLayers.OnChange := doOnChangeLayers;

// click on bubble
procedure TForm.doOnClick(sender: TObject; const item: TECShape);
begin
caption := TECBubbleLayer(sender).Name + ' : ' + item.PropertyFormat(item.Hint);
end;

// right click on bubble
procedure TForm.doOnRightClick(sender: TObject; const item: TECShape);
begin
caption := TECBubbleLayer(sender).Name + ' : ' + item.PropertyFormat(item.Hint)+' (Right)';
end;

// event triggered after the automatic creation
// you can modify your element as you wish, to change its shape and color for example
procedure TForm.doOnEditBubble(const BubbleShape:TECShapePoi);
begin

if BubbleShape['shape']= '1' then
begin
BubbleShape.POIShape := poiDiamond;
BubbleShape.Color := getInvertColor(BubbleShape.color);
end;

end;

// event triggered after add or delete TECBubbleLayer
procedure TForm.doOnChangeLayers(sender : TObject);
begin
Map.BubbleLayers.getLayers(Layers.Items) ;
delete.Enabled := layers.ItemIndex>-1;
end;

TECBubbleLayer

procedure Clear;
Efface l'ensemble des éléments du layer

function Add(const Lat, Lng, Size: double;const properties:string=''): TECBubbleItem;


function Add(const location: string; Size: double;const properties:string=''): TECBubbleItem;

Ajoute un élément par sa position GPS ou par son adresse
procedure Delete(const index: integer);
Efface un élémént
procedure fitBounds;
Ajuste le zoom pour afficher l'ensemble des éléments
procedure Update;
Met ajour l'affichage du layer, tant que vous n'appelez pas Upate les modifications ne sont pas répercutées sur la carte.

property Color: TColor

property UseColorPalette: boolean

property ColorPalette: THeatPalette

Palette qui calcule une couleur en fonction de l'échelle de l'élément

Fig. 14 Palette de couleurs par défaut

// addColor(Red,Green,Blue,Value)
// Red,Green, and Blue byte 0..255
// value double 0..1,
// value corresponds to a percentage
// 0.5 is equivalent to an element that is half the size of the largest

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

Layer.ColorPalette.AddColor(0,0,0,0); // black for value=0
Layer.ColorPalette.AddColor(0,0,255,0.1);// blue for value=0.1
Layer.ColorPalette.AddColor(0,255,255,0.25); // cyan for value=0.25
Layer.ColorPalette.AddColor(0,255,0,0.5); // green for value=0.5
Layer.ColorPalette.AddColor(255,255,0,0.75); // yellow for value=0.75
Layer.ColorPalette.AddColor(255,0,0,1); // red for value=1
property Count: integer ;
Nombre d'éléments

property HintProperty: string

Propriété qui servira de Hint pour l'élément
property Hint : string
Hint par défaut pour les éléments

property MaxItemSize: integer

property MinItemSize: integer

property Labels: TLabelShape

Gestion des labels

property Opacity: byte

property shape: TPOIShape

property MaxZoom: byte

property MinZoom: byte

Plage de zoom d'affichage du layer

property Name: string

property List[const index: integer]: TECBubbleItem

Liste des éléments

property ZIndex: integer

ZIndex du layer permet de gérer le recouvrement des différents layers
// Attention each request of localization makes an Internet request,
// in the cumulated it takes time
// the best is to use directly the GPS coordinates
// here it is used for documentation purposes
procedure TForm10.Add_5_Most_Populated_FR_cities;
var FBubbleLayer : TECBubbleLayer;
begin

FBubbleLayer := Map.BubbleLayers.Add('5 Most Populated FR cities');
// Global Hint where the properties of each element will be injected
FBubbleLayer.Hint := '[size] inhabitants in [location] in 2020';
// the color will be determined according to the size using the layer's color palette
FBubbleLayer.UseColorPalette := true;
// the size of the elements will be scaled between 60 and 100 pixels depending on size
FBubbleLayer.MinItemSize := 60;
FBubbleLayer.MaxItemSize := 100;
// labels will be displayed for zoom 5 and more
FBubbleLayer.Labels.MinZoom := 5;
// the label will be composed of the properties 'location' and 'size'
FBubbleLayer.Labels.LabelMask := '[location]'+#13#10+'[size]';
FBubbleLayer.Labels.LabelType := ltMask;

// the position is determined by their location
// its size by the number of inhabitants

FBubbleLayer.Add('Paris,FR',2145906);
FBubbleLayer.Add('Marseille,FR',870321);
FBubbleLayer.Add('Lyon,FR',522228);
FBubbleLayer.Add('Toulouse,FR',498003);
FBubbleLayer.Add('Nice,FR',343477);

// Add('location',size) automatically sets the 'location' and 'size' properties
// you can add properties with these two syntaxes
// var bubble:TECBubbleItem;
// bubble := FBubbleLayer.Add('Paris,FR',2145906,'prop1=data1,prop2=data2');
// bubble['propx'] := 'datax';


// update of the layer display
FBubbleLayer.Update;
// zoom in to show all elements
FBubbleLayer.fitBounds;


end;

Chart Layer

Ce calque permet d'afficher des diagrammes circulaires ou des barres empilées.


Fig. 15 Barres empilées verticales

Fig. 16 Diagrammes circulaires type "pie"

Fig. 17 Diagrammes circulaires type "donut"

TECChartLayers

Gestionnaire de layers TECChartLayer

function Add(const Name: string): TECChartLayer;
Ajoute un layer
procedure Delete(const Name: string);
procedure Delete(const index: integer);
Détruit un layer spécifié par son nom ou son index
procedure Clear;
Détruit tous les layers
function getLayers(const aList: TStrings): integer;
Rempli aList avec la liste des layers et retourne leur nombre
property Count: integer
Nombre de layers
property MaxItemSize: integer
property MinItemSize: integer
Pour les diagrammes circulaires cela indique le rayon maximal et minimal, la longueur pour les barres
la taille des éléments sera échelonnée entre MinItemSize et MaxItemSize pixels
property BarThickness : integer
Épaisseur des barres, par défaut 16 pixels
property Layer[const index: string]: TECChartLayer
property List[const index: integer]: TECChartLayer
Retourne un layer en fonction de son nom ou de son index
property Opacity: byte
Opacité des éléments
property ChartType: TECChartType
Forme des diagrammes (ctPie, ctDonut, ctFillDonut,ctVerticalStackedBar,ctHorizontalStackedBar)
property OnChange: TNotifyEvent
Déclenché lors de l'ajout ou de la suppression d'un layer
property OnClick: TOnShapeMouseEvent
Click sur un élément
property OnRightClick: TOnShapeMouseEvent
Click droit sur un élément

Vous retrouvez la plus part de ses propriétés au niveau du layer, cela vous permet de les centraliser.

10
// click on chart
procedure TFormChartLayer.doOnClick(Sender: TObject; const item: TECShape);
begin
caption := 'Click Left - '+TECchartLayer(Sender).Name +
' : Chart n°'+inttostr(item.IndexOf)+' Total =' + item['total'] ;
// if needed you can access TECChartItem with TECChartItem(item.item)
end;
// right click on chart
procedure TFormChartLayer.doOnRightClick(Sender: TObject; const item: TECShape);
begin
caption := 'Click Right - '+TECchartLayer(Sender).Name +
' : Chart n°'+inttostr(item.IndexOf)+' Total =' + item['total'] ;
end;

procedure TFormChartLayer.FormCreate(Sender: TObject);
begin
map.ChartLayers.OnChange := doOnChangeLayers;
map.ChartLayers.OnClick := doOnClick;
map.ChartLayers.OnRightClick := doOnRightClick;

// The size of the diagrams will also be adapted according to the zoom
map.ScaleMarkerToZoom := true;

tag := 0;
TotalLayer := 0;
end;

TECCharLayer

procedure Clear;
Efface l'ensemble des diagrammes
function AddField(const Legend: string; Color: TColor): integer;
Ajoute un champ aux diagrammes
function Add(const Lat, Lng: double; const Properties: string = '') : TECChartItem;
Ajoute un diagramme à la position géographique Lat,Lng
procedure Delete(const index: integer);
Supprime un diagramme
procedure fitBounds;
Zoomer sur les diagrammes
procedure Update;
Création de l'ensemble des diagrammes, tant que Update n'est pas appelé les modifications ne sont pas répercutées.
property Caption: string
Titre de votre layer, il pourra vous servir pour légender

property BarThickness : integer

property Color: TColor

property BorderColor: TColor

property Count: integer
Nombre de diagramme
property Fields: TECAChartField
Ensemble des champs de vos diagrammes

property HintColor: TColor

property Labels: TLabelShape
Gestion des labels

property MaxChartSize: integer

property MinChartSize: integer ;

property Opacity: byte

property ChartType: TECChartType

property MaxZoom: byte

property MinZoom: byte

property Visible : boolean

property Name: string


property List[const index: integer]: TECChartItem ;

Liste des diagrammes, accédez-y pour remplir les valeurs des champs
property Sort: TECChartDataSort
Par défaut les valeurs des champs sont sorties en ordre décroissant, vous avez le choix entre cdsNone, cdsAscending et cdsDescending

property ZIndex: integer

property OnClick: TOnShapeMouseEvent

property OnRightClick: TOnShapeMouseEvent

property OnValidHint : TOnValidHint

const
// palettes from https://colorbrewer2.org
palettes : array [0..2]of array [0..7] of string = (
('#7fc97f','#beaed4','#fdc086','#ffff99','#386cb0','#f0027f','#bf5b17','#666666'),
('#d53e4f','#f46d43','#fdae61','#fee08b','#e6f598','#abdda4','#66c2a5','#3288bd'),
('#66c2a5','#fc8d62','#8da0cb','#e78ac3','#a6d854','#ffd92f','#e5c494','#b3b3b3')

);

// change default hint legend
procedure doOnValideHint(const Sender: TECChartItem; const index: integer;
const percent, value: double; var hint: string);
begin

// a positive index indicates a data line
if index >-1 then

hint := Sender.Layer.Fields[index].Legend + ' : ' + doubletostrdigit(percent,
1) + ' % (' + doubletostr(value) + ')'

else // -1 indicates that the legend is complete, you can enrich it

Hint := '<h3><center>'+sender.Layer.Caption+ '</center></h3>'+
hint+
'<h4><center>Chart n°'+inttostr(sender.Shape.IndexOf)+'</center></h4>';

end;

// create random layer
procedure TFormChartLayer.addLayerClick(Sender: TObject);
var
Lat, Lng: double;
x, y, i,id_pal, delta_lat, delta_lng: integer;
s: string;
FChartLayer: TECChartLayer;
FChartType: TECChartType;
chart: TECChartItem;
begin

// cycle chart type
case tag of
0:
begin
FChartType := ctPie;
s := 'Pie';
end;
1:
begin
FChartType := ctDonut;
s := 'Donut';
end;
2:
begin
FChartType := ctFillDonut;
s := 'FillDonut';
end;
3:
begin
FChartType := ctVerticalStackedBar;
s := 'VerticalStackedBar';
end;
else
begin
FChartType := ctHorizontalStackedBar;
s := 'HorizontalStackedBar';
end;

end;

tag := tag + 1;
if tag>4 then tag := 0;

// create layer
FChartLayer := map.ChartLayers.Add(s + ' ' + timeTosTr(time));

inc(TotalLayer);
FChartLayer.Caption := 'Title Chart Layer ' + inttostr(TotalLayer);

// adapt the graph legend
FChartLayer.OnValidHint := doOnValideHint;

// create random datas

// select palette
id_pal := random(3);

// between 4 and 8 lines of data
for i := 0 to 3 + random(5) do
FChartLayer.AddField('Data ' + chr(i + ord('A')), StrToColor(palettes[id_pal][i]));

FChartLayer.ChartType := FChartType;

// labels will be displayed for zoom 3 and more
FChartLayer.Labels.MinZoom := 3;

if FChartLayer.ChartType < ctVerticalStackedBar then
begin
// max radius 50
FChartLayer.MaxChartSize := 50;
FChartLayer.Labels.Align := laCenter;
end
else // stacked bar
begin
// max bar size 100
FChartLayer.MaxChartSize := 100;
FChartLayer.Labels.Align := laBottom;
end;

FChartLayer.MinChartSize := 16;

// distribute 4 * 4 graphs on the visible surface of the map
delta_lat := round(((map.NorthEastLatitude - map.SouthWestLatitude) * 1000));
delta_lng := round(((map.NorthEastLongitude - map.SouthWestlongitude) * 1000));

for y := 0 to 3 do
begin
for x := 0 to 3 do
begin

Lat := map.SouthWestLatitude + (random(delta_lat) / 1000);
Lng := map.SouthWestlongitude + (random(delta_lng) / 1000);

// create chart
chart := FChartLayer.Add(Lat, Lng);

// add ramdom value
// automatically sets the 'total' propertie
for i := low(FChartLayer.Fields) to High(FChartLayer.Fields) do
chart.data[i] := random(100) + random(99);

end;
end;

// generate the elements on the map
FChartLayer.Update;

// zoom it
FChartLayer.fitBounds;

layers.ItemIndex := layers.Items.Count - 1;
Delete.Enabled := true;

end;

AirQuality

Ce layer affiche le taux de pollutions de l'air dans le monde, il utilise les donnés du projet World Air Quality Index

Fig. 18 Demo AirQuality

procedure getJSON(const Lat, Lng: double)


Demande les données de la station la plus proche du point GPS

procedure getJSON(const city: string)

Demande les données d'une station dont on indique le nom

procedure getJSON(const Lat, Lng, lat2, lng2: double)

Demande les stations qui se trouvent dans la zone indiquée

Les données sont retournées au format JSON, l'évènement OnJson est déclenché dès qu'elles sont disponibles.
L'évènement OnRequest est déclenché lorsque la requête est lancée.

11
procedure TFormAirQuality.FormCreate(Sender: TObject);
begin
// get your free key from https://aqicn.org/data-platform/token/
map.AirQuality.key := '';
map.AirQuality.OnJson := doOnJson;
map.AirQuality.OnClick := doOnclick;
map.AirQuality.OnRequest := doOnRequest;
map.AirQuality.visible := true;
end;

/// Request the list of stations located in the visible area of the map.
/// The list is returned in json format, the OnJson event is triggered as soon as it is available
procedure TFormAirQuality.getallstationsClick(Sender: TObject);
begin
map.AirQuality.getJSON(map.SouthWestLatitude,map.SouthWestLongitude,map.NorthEastLatitude,map.NorthEastLongitude);
end;

/// Request data from the station closest to the center of the map
/// Data is returned in json format, the OnJson event is triggered as soon as it is available
procedure TFormAirQuality.GetStationClick(Sender: TObject);
begin
map.AirQuality.getJSON(map.Center.Lat,map.Center.Lng);
end;

/// Triggered when the response of a call to getJSON is available
/// The response is contained in Json, Query contains the parameters of the request
procedure TFormAirQuality.doOnJson(sender: TObject; const Query, JSon: string) ;
begin
MJson.Lines.Text := Json;
end;

/// Triggered just before call getJSON or click on Station
procedure TFormAirQuality.doOnRequest(sender : TObject);
begin
MJson.Lines.Text := 'result pending...';
end;

function JsonToAirQualityCity(const json:string):TAirQualityCity

Traite les données json obtenu par GetJSon pour remplir un record TAirQualityCity
TAirQualityCity = record
Query,
Json,
Name: string;
latitude: double;
longitude: double;
DominantPollutant: TAirQualityItem;
Pollutants: TAirQualityPollutants;
Weather: TAirQualityWeather;
IsoTime: string;
Time: TDateTime;
level: TAirQualityLevel;
LevelColor: TColor;
end;

property AirQualityIndex: TAirQualityIndex


Choix de l'index principal affiché sur les tuiles

Par défaut usepa_aqi qui indique le polluant principal

TAirQualityIndex = (usepa_aqi, usepa_pm25, usepa_10, usepa_o3, usepa_no2,usepa_so2, usepa_co, asean_pm10);

property Key: string

Renseignez cette propriété avec la clef d'api gratuite que vous obtenez à cette adresse aqicn.org/data-platform/token/

property Visible: boolean

Gérer l'affichage du layer.

property City: TAirQualityCity

Donnée de la dernière station survolée ou clickée.

Pour que la requête soit déclenchée il faut que OnClick ou OnHover soit renseigné.

12

property OnJson: TAirQualityOnJson

Événement déclenché lorsque les données demandées par GetJSON sont disponibles

property OnClick : TAirQualityEvent

Événement déclenché lorsque les données de la station clickée sont disponibles

property OnHover : TAirQualityEvent


Événement déclenché lorsque les données de la station survolée sont disponibles

property OnRequest : TNotifyEvent

Événement déclenché lorsqu'une requête est lancée et avant que le résultat ne soit disponible
// Triggered after a click on a station when data is available
procedure TFormAirQuality.doOnclick(const sender : TAirQualityCity);
var i:integer;
level:string;
begin
// all data in json format are available in sender.Json

MJSon.text := #13#10+ map.AirQuality.Legend[sender.Level]+#13#10#13#10;

MJSon.Lines.Add(Sender.Name);

MJson.Lines.Add('IQ '+DoubleToStr(Sender.DominantPollutant.Value));

for i := 0 to High(sender.Pollutants) do
MJson.Lines.Add(Sender.Pollutants[i].Name+' = '+DoubleToStr(sender.Pollutants[i].value));

for i := 0 to High(sender.weather) do
MJson.Lines.Add(sender.weather[i].Name+' = '+DoubleToStr(sender.weather[i].value));

MJSon.Lines.Add('');
MJSon.Lines.Add(sender.IsoTime);
MJSon.Lines.Add(DateTimeToStr(sender.Time));

MJSon.Color := sender.LevelColor;
MJSon.Font.Color := GetContrastingColor(sender.LevelColor);
end;

Layer WMS

La propropriété WMSLayers du composant TECNativeMap vous permet de gérer une lise de layer WMS

varWMS_Cadastre : TECNativeWMS;
...
WMS_Cadastre := map.WMSLayers.Add('https://geobretagne.fr/geoserver/cadastre/wms', // url service
'CP.CadastralParcel', // layer
'CADASTRE' // TECNativeMap group name
);
TECWMSLayers
function Count: integer;
procedure Refresh;
procedure Clear;
function Add(const Url, layers, Name: string): TECNativeWMS;

Vous pouvez indiquer plusieurs layers en les séparant par une virgule

13
procedure Delete(const Name: string);
procedure Delete(const index: integer);
procedure Delete(const index: TECNativeWMS);
function IndexOf(const Name: string): integer;
property Layer[const index: integer]: TECNativeWMS; default
property Layer[const index: string]: TECNativeWMS; default

property OnCapabilities : TNotifyEvent

Déclenché lorsque les données du service associé à un layer sont disponibles.

property OnFeatureInfo : TNotifyEvent

Déclenché lorsque les informations sur un éléments du layer sont disponibles

property OnEnabled : TNotifyEvent

Déclenché lorsque la vue de la carte entre ou sort de la zone de couverture du layer

property OnChangeTimeDimension

Déclenché à chaque changement de période lorsque le TimeDimension du layer est activé

property OnLoadingTimeDimension

Déclenché lorsque des tuiles du TimeDimension du layer sont chargées, LoadingPercentTimeDimension est à 100 si toutes les tuiles sont disponibles
map.WMSLayers.OnLoadingTimeDimension := doOnLoadingTimeDimension;
...
// event triggered when TimeDimension tiles is loading
procedure TFormWMS_WFS.doOnLoadingTimeDimension(Sender: TObject);
var
WMSLayer: TECNativeWMS;
begin
if Sender is TECNativeWMS then
begin

WMSLayer := Sender as TECNativeWMS;
if assigned(WMSLayer) then
begin
TimeLoading.Position := WMSLayer.LoadingPercentTimeDimension;
TimeLoading.Visible := WMSLayer.LoadingPercentTimeDimension< 100;
end;
end
end;

property OnEnabledTimeDimension

Déclenché lors de l'activation / désactivation du TimeDimension du layer
// connect WMS events
map.WMSLayers.OnCapabilities := doOnCapabilities;
map.WMSLayers.OnFeatureInfo := doOnFeatureInfo;
map.WMSLayers.OnEnabled := doOnEnabled;
map.WMSLayers.OnChangeTimeDimension := doOnChangeTimeDimension;
map.WMSLayers.OnEnabledTimeDimension := doOnEnabledTimeDimension;
...
// OnEnabled is triggered when the visible area of the map moves in or out of the layers.
// When Enabled is false, no more requests are made to the server.
procedure TFormWMS_WFS.doOnEnabled(Sender: TObject);
var
WMSLayer: TECNativeWMS;
begin

if Sender is TECNativeWMS then
begin

WMSLayer := Sender as TECNativeWMS;
if assigned(WMSLayer) then
begin
events.lines.Add(WMSLayer.Name + ' ENABLED : ' +
BoolToStr(WMSLayer.Enabled));
end;
end

end;

// event triggered each time the TimeDimension enabled/disable
procedure TFormWMS_WFS.doOnEnabledTimeDimension(Sender: TObject);
var
WMSLayer: TECNativeWMS;
begin

if Sender is TECNativeWMS then
begin

WMSLayer := Sender as TECNativeWMS;
if assigned(WMSLayer) then
begin
events.lines.Add(WMSLayer.Name + ' TIMEDIMENSION ENABLED : ' +
BoolToStr(WMSLayer.TimeDimension.Enabled));
end;
end

end;


// event triggered each time the TimeDimension period changes
procedure TFormWMS_WFS.doOnChangeTimeDimension(Sender: TObject);
var
WMSLayer: TECNativeWMS;
begin

if Sender is TECNativeWMS then
begin

WMSLayer := Sender as TECNativeWMS;
if assigned(WMSLayer) then
begin
Time.Caption := WMSLayer.Time;
end;
end

end;


// A GetCapabilities request is automatically made to the server,
// when the data is available OnCapabilities is triggered
// and the data is available in the Capabilities string.
// You can restart a request using the GetCapabilities procedure
procedure TFormWMS_WFS.doOnCapabilities(Sender: TObject);
var
WMSLayer: TECNativeWMS;
begin

if Sender is TECNativeWMS then
begin

WMSLayer := Sender as TECNativeWMS;
if assigned(WMSLayer) then
begin

// show Bounding Box
events.lines.Add(WMSLayer.Name + ' BBOX :' +
doubletoStrDigit(WMSLayer.SWLat, 6) + ' ' +
doubletoStrDigit(WMSLayer.SWLng, 6) + ' ' +
doubletoStrDigit(WMSLayer.NELat, 6) + ' ' +
doubletoStrDigit(WMSLayer.NELng, 6));

end;
end

end;

// A GetFeatureInfo request is automatically made to the server,
// when the data is available OnFeatureInfo is triggered
// and the data is available in the FeatureInfo string.
// You can restart a request using the GetFeatureInfo procedure
procedure TFormWMS_WFS.doOnFeatureInfo(Sender: TObject);
var
WMSLayer: TECNativeWMS;
begin

if Sender is TECNativeWMS then
begin

WMSLayer := Sender as TECNativeWMS;
if assigned(WMSLayer) then
begin
events.lines.Add('GET FEATUREINFO : ' + WMSLayer.Name);
end;
end

end;

TECNativeWMS
property Capabilities: string;
Retourne les données qui décrivent le contenu du service et les paramètres acceptés.
Elles sont récupérés dans un Thread, l'événement TECWMSLayers.OnCapabilities est activé lorsqu'elles sont disponibles.

property FeatureInfo: string;
retourne des informations sur un objet représenté sur la carte.
Elles sont récupérés dans un Thread, l'événement TECWMSLayers.OnFeatureInfo est activé lorsqu'elles sont disponibles
property layers: string
Le ou les layers demandés
property Styles: string
liste des styles utilisés pour les layers
property Time: string

Permet de spécifier une date sous la forme du chaine au format ISO 8601.

Laissez vide pour obtenir les données les plus récentes

property TimeDimension : TECTimeDimension
Permet de changer la propriété Time sur un intervale de temps
var datetime:TDateTime;
// set Minute and seconde to 0
datetime := SetHourMinuteSeconde(Now, -1, 0, 0);
// show last hour
WMS_Layer_Radar.TimeDimension.StartTime := decHour(datetime, 1);
WMS_Layer_Radar.TimeDimension.EndTime := datetime;
// period 5 minutes
WMS_Layer_Radar.TimeDimension.PeriodMillisecondes := 5 * 60 * 1000;
WMS_Layer_Radar.TimeDimension.TransitionMillisecondes := 500;
// You can also directly pass an array of TDateTime
// WMS_Layer_Radar.TimeDimension.AddTime([datetime1, datetime2,..,datetimex]);
// loop
WMS_Layer_Radar.TimeDimension.Loop := true;
// activate timedimension
WMS_Layer_Radar.EnabledTimeDimension := true;

procedure StartTimeDimension;

Afficher la première date

procedure EndTimeDimension;

Afficher la dernière date

procedure NextTimeDimension;

Afficher la date suivante

procedure PrevTimeDimension;

Afficher la date précédente

property PauseTimeDimension: boolean

Activer/Désactiver la pause

Fig. 19 Precipitation radar TimeDimension

property Url: string

Url du serveur
property Version: string
Chaine contenant la version du serveur sous la forme '1.0.0', par défaut '1.1.0';
property Legend: boolean
Permet d'afficher une image contenant la légende des données retournées
property LegendWidth: integer
property LegendHeight: integer
property LegendOpacity: byte
Réglage de l'opacité de la légende de 0 à 100
property LegendPosition: TLegendPosition
Au choix parmi : pTopLeft, lpTopRight, lpBottomLeft, lpBottomRight, lpTopCenter, lpBottomCenter, lpLeftCenter, lpRightCenter
property LegendXMargin: integer
Marge en pixel pour le décalage horizontal par rapport au bord de la carte
property LegendYMargin: integer
Marge pour le décalage vertival par rapport au bord de la carte
property LayersList : TAECRecordLayers

Tableau de TECRecordLayer qui contient les informations sur les layers disponibles sur le serveur, ce tableau est rempli après l'appel à getCapabilities, vous pourrez y avoir accès dès que OnCapabilities aura été déclenché.

getCapabilities est automatiquement appelé lors de la creation du layer.

14

TECRecordLayer = record
Name : string;
Title : string;
NELat,
NELng,
SWLat,
SWLng : double;
end;

Voir la demo WFS-WMS-Capabilities-List pour un exemple d'utilisation

Fig. 20 WMS layers list

property Name: string
Nom du groupe qui contient les données du layer
property Visible : boolean
Activation du layer
WMS_Layer_Radar := map.WMSLayers.Add('https://maps.dwd.de/geoserver/ows', // url service
'dwd:Niederschlagsradar', // layer
'RADAR' // TECNativeMap group name
);

WMS_Layer_Radar.Version := '1.3.0';
WMS_Layer_Radar.ZIndex := 20;
WMS_layer_Radar.Legend := true;
// opacity 0..100
WMS_layer_Radar.LegendOpacity := 75;
WMS_layer_Radar.LegendPosition := lpRightCenter;
WMS_Layer_Radar.Visible := true;

Layer WFS

La propropriété WFSLayers du composant TECNativeMap vous permet de gérer une lise de layer WFS

Ces layers possèdent eux aussi un tableau permettant d'accéder à l'ensemble des features disponible.

property FeatureTypeList : TAECRecordFeatures
TECRecordFeature = record
FType : string;
Name : string;
Title : string;
NELat,
NELng,
SWLat,
SWLng : double;
end;

Voir la demo WFS-WMS-Capabilities-List pour un exemple d'utilisation

Fig. 21 WFS features list

Le service WFS doit pouvoir exporter au format JSON pour que TECNativeMap puisse l'interpréter !

2
var WFS_Layer_Us : TECNativeWFS;
...
WFS_Layer_Us := map.WFSLayers.Add(
'https://geoserver.geoplatform.gov/geoserver/ngda/ows', // url service
'ngda:473c080c_8686_41d6_b1ee_6945e5c924f3' // layer
,'US-STATICAL-AREA' // TECNativeMap group name
);

// respond to a click on a layer element
WFS_Layer_Us.OnShapeClick := doShapeClick;

// default values for polygones
map.Styles.addRule('#US-STATICAL-AREA.polygone {weight:1;color:black;}');
// when a polygon is hovered over with the mouse, the outline thickness is 3 pixels
// the fill color is red
map.Styles.addRule('#US-STATICAL-AREA.polygone:hover {weight:3;hcolor:red;}');
// polygons with an 'lsad' property value of 'M1' are greyed out
map.Styles.addRule('#US-STATICAL-AREA.polygone.lsad:M1 {fcolor:gray;hbcolor:light(gray)}');
// polygons with an 'lsad' property value of 'M2' are blue
map.Styles.addRule('#US-STATICAL-AREA.polygone.lsad:M2 {fcolor:blue;hbcolor:light(blue)}');

WFS_Layer_Us.MaxFeature := 10000;

// Limit queries to the area bounded by the North-East and South-West corners
// NELat = 50 , NELng = -63
// SWLat = 31 , SWLng = -121
// To accept requests for the whole world (default) : WFS_Layer_Us.BoundingBox;
WFS_Layer_Us.BoundingBox(50,-63,31,-121) ;

// No query if zoom > 10
WFS_Layer_Us.MaxZoom := 10;

// Round off the search area on the corners of the tiles,
// this will allow caching and limit requests to the server.
WFS_Layer_Us.RoundBoxToTiles := true;

// Each time the map is moved, the new zone is queried (taking into account the various limits).
WFS_Layer_Us.AutoRefresh := true;

WFS_Layer_Us.visible := true;

// respond to a click on a layer element
procedure TFormWMS_WFS.doShapeClick(sender: TObject; const item: TECShape);
var Key, Value, content: string;
win: TECShapeInfoWindow;
begin
if not assigned(item) then exit;

content := '';
// extract all properties and their values,
// enriching them for a more readable display
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;

if content='' then exit;

// retrieve the WFSLayer stored in the Data property of the clicked element's group
if item.Group.Data is TECNativeWFS then
begin
// we use its infoWindow, but we could use any infoWindow,
// in which case we'd have to ensure that its group ZIndex is greater than that of the WFSLayer
win := TECNativeWFS(item.Group.Data).InfoWindow;
win.content := content;
win.SetPosition(map.MouseLatLng.Lat, map.MouseLatLng.lng);
win.Visible := true;
end;
end;

Fig. 22 WFS Layer

Aller à la page
Réalisé avec la version gratuite pour les particuliers d'Help&Web