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;



Vous pouvez soit vous brancher sur OnMapHiResChange soit surcharger la procedure doOnMapHiResChange(sender : TObject) pour que votre layer s'adapte au changement de résolution

38

Panoramio

Google a fermé Panoramio le 4 novembre 2016, le service n'est plus fonctionnel

Un layer Panoramio est intégré dans TECNativeMap au travers de la propriété PanoramioLayer

// show panoramio layer
map.PanoramioLayer := true;




L'évenement OnPanoramioClick(sender: TObject; const Item: TECShape; const ownerId, ownerName, PhotoId, PhotoDate, PhotoTitle, PhotoUrl, copyright: string) est déclenché lors d'un clic sur un élément Panoramio.

Fig. 147 Click sur un élément Panoramio

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

104

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. 148 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

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

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

Fig. 150 'highway=bus_stop'

Way

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

// 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. 151 Xapi Way

Vous pouvez aussi trouver les jonctions entres les routes.

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

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

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

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

36

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

105

Utilisez TECMapillaryLayer pour incorporer un layer Mapillary.

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

FMappilaryLayer.Visible := true;

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

106

Fig. 154 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
// load mapillary image 256x256 in a TImage
bmp := TBitmap.Create;
try

// also url1024 and url2048

if FMapillaryLayer.LoadMapillaryBitmap(Sequence[ImageIndex].Url256,bmp) then

Image.Picture.Assign(bmp);

finally
bmp.Free;
end;

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

107

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

108

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.

109
Layer.OnSequenceColor := doSequenceColor;

procedure TForm2.doSequenceColor(Layer : TECMapillaryLayer;
MapillarySequence: TMapillarySequence;
var SequenceColor:TColor);
begin
SequenceColor := your_color;
end;

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. 155 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. 156 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) ;
Aller à la page
Composant Delphi / Google Maps / OpenStreetMap / Leaflet  / Mappilary© 2016 ESCOT-SEP Christophe - Réalisé avec Help&Web - RSS - RSS - Google+