TECNativeMap permet d'enregistrer et de recharger la totalité de ses données dans un simple fichier texte, cela comprend non seulement les paramètrages du composant et des vues mais aussi les données cartographiques
Vous pouvez aussi importer/exporter vos données aux formats GPX , GeoJSON et KML
Sauvegarde/Restauration
Enregistre la carte dans un fichier texte.
Utilisez les extensions .gpx , .kml pour spécifier un format, autrement c'est le format interne d'ECNativeMap qui sera employé
Charge la carte avec un fichier texte
Utilisez les extensions .osm, .olt, .gpx, .json , .kml ou .csv pour spécifier un format, autrement c'est le format interne d'ECNativeMap qui sera employé
LoadFromFile peut télécharger les fichiers sur internet
1
Propriété en lecture/écriture qui donne accès aux données de la carte dans le format GPX.
Cette propriété est utilisée par SaveToFile, LoadFromFile.
Propriété en lecture/écriture qui donne accès aux données de la carte dans un format texte.
Cette propriété est utilisée par SaveToFile, LoadFromFile.
Propriété en lecture / écriture qui retourne les éléments géographique de la carte au format Kml
Propriété en lecture/écriture qui donne accès aux données de la carte dans le format GeoJson.
Vous accédez aux données du champ "properties" avec TECShape.Properties, reportez vous au chapitre sur les Tuiles vectorielles pour apprendre à styler vos éléments.
Cette propriété est utilisée par SaveToFile, LoadFromFile.
Évenements
Lorsque le chargement d'un fichier (.csv, .kml, .geojson, .gpx ou .txt) est terminé l'événement OnLoad(sender: TObject; const GroupName: string; const FinishLoading: Boolean); se déclenche.
...
// fired when load ready
procedure TForm.mapLoad(sender: TObject; const GroupName: string;
const FinishLoading: Boolean);
begin
// show all éléments
map.group[groupname].fitbounds;
end;
Pendant le chargement de la carte l'évenement OnLoadShapes(sender: TObject;const ShapeType:string;const index,max:integer;var cancel:boolean) se déclenche pour chaque élement ajouté.
ShapeType peut prendre les valeurs 'TECShapePOI', 'TECShapeMarker', 'TECShapeLine' , 'TECShapePolygone' et 'TECShapeInfoWindow'.
Index indique le numéro de l'élément actuellement chargé et Max le nombre total d'éléments à charger.
Vous pouvez abandonner le chargement en basculant cancel à true
Lorsque le fichier à été chargé l'événement OnLoad(sender: TObject;const GroupName:string;const FinishLoading : boolean)
GroupName contient le nom du groupe qui a été chargé, vide pour un chargement direct de la carte (groupe par défaut)
FinishLoading vaut true si le fichier a été chargé en totalité et false s'il a été abandonné en basculant cancel à true
OSM XML
Vous pouvez directement charger un fichier au format
OSM XML ou olt avec LoadFromFile.
Les groupes disposent en plus des fonctions
LoadFromOSMStream et
LoadFromOSMString.
La classe TOSMFile de l'unité uecOSM vous permet de travailler avec des fichiers au format OSM XML ( format de base d'OpenStreetMap ).
Vous pouvez télécharger des régions du monde dans ce format sur le site geofabrik.de, prenez les fichiers .osm.bz2 et dézippez-les
Mais vous pouvez aussi obtenir ces données directement depuis TECNativeMap en utilisant OverPass API
OverPassApi
La propriété OverPassApi vous permet d'utiliser Overpass API pour obtenir des données d'OpenStreetMap
Un layer est aussi disponible pour simplifier l'utilisation
1Par défaut le serveur utilisé est https://overpass-api.de/api/interpreter, pour le changer utilisez la propriété Url
Les requêtes ne sont pas bloquantes, branchez vous sur l'événement OnData pour récupérer les données lorsqu'elles sont disponibles.
Utilisez Query pour lancer votre requête.
// get highway
map.OverPassApi.Query('way({{bbox}})[highway][name];(._;>;);out;)');
// the event is triggered when data is available
procedure TForm.doOverPass(const value:TECOverPassData);
begin
// load OSM data in your map
map.Shapes.LoadFromOSMString(value.Data);
end;
Vous pouvez utiliser {{bbox}} pour limiter la recherche à la zone visible de votre carte, et {{center}} pour indiquer le point central de votre carte.
2Pour plus d'information sur le langage de script d'OverPassAPI consultez :
wiki.openstreetmap.org/wiki/Overpass_API/Language_Guidewiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL
Quelques requêtes sont disponibles en standard
StreetNames retourne juste une liste contenant le nom des rues
procedure StreetNames(const bbox:string='';const OnDataEvent:TECOnOverPass=nil); overload;
Utilisez cette version pour définir une zone de recherche différente de la vue actuelle
procedure StreetNames(const SWLatitude,SWLongitude,NELatitude,NELongitude:double;const OnDataEvent:TECOnOverPass=nil); overload;
Streets retourne les données OSM pour les rues de la zone choisi (c'est l'équivalent de l'exemple plus haut)
procedure Streets(const SWLatitude,SWLongitude,NELatitude,NELongitude:double;const OnDataEvent:TECOnOverPass=nil); overload;
Amenity permet de trouver des points spécifiques
const data:TSetOSMData=[odNode,odWay];
const bbox: string = '';
const OnDataEvent: TECOnOverPass = nil); overload;
procedure Amenity(const SWLatitude, SWLongitude, NELatitude,NELongitude: double;
const amenity_value: string = '';
const data:TSetOSMData=[odNode,odWay];
const OnDataEvent: TECOnOverPass = nil); overload;
procedure Amenity( const amenity_values: array of string;
const data:TSetOSMData=[odNode,odWay];
const Op: TBinaryFilterOSM = bfAnd;
const bbox: string = '';
const OnDataEvent: TECOnOverPass = nil); overload;
procedure Amenity( const SWLatitude, SWLongitude, NELatitude,NELongitude: double;
const amenity_values: array of string;
const data:TSetOSMData=[odNode,odWay];
const Op: TBinaryFilterOSM = bfAnd;
const OnDataEvent: TECOnOverPass = nil); overload;
// find all 'restaurant' (Node and Way) in visible area
map.OverPassApi.Amenity('restaurant');
// find all 'restaurant' (only Node) in visible area
map.OverPassApi.Amenity('restaurant',[odNode]);
// the event is triggered when data is available
// Set OnDataEvent to connect to a specific procedure
procedure TForm.doOverPass(const value:TECOverPassData);
begin
// load OSM data in your map
map.Shapes.LoadFromOSMString(value.Data);
end;
map.OverPassApi.Amenity('restaurant',[odNode],'',myEvent);
...
procedure TForm.myEvent(const value:TECOverPassData);
begin
// load OSM data in your map
map.Shapes.LoadFromOSMString(value.Data);
end;
Tag est la procedure générique pour chercher parmis l'ensemble des key pas seulement Amenity
const Data:TSetOSMData=[odNode,odWay];
const Op: TBinaryFilterOSM = bfAnd;
const bbox: string = '';
const OnDataEvent: TECOnOverPass = nil); overload;
procedure Tag(const tag_name:string;
const tag_values: array of string;
const data:TSetOSMData=[odNode,odWay];
const Op: TBinaryFilterOSM = bfAnd;
const bbox: string = '';
const OnDataEvent: TECOnOverPass = nil); overload;
procedure Tag(const tag_name: string = '';
const tag_value: string = '';
const data:TSetOSMData=[odNode,odWay];
const bbox: string = '';
const OnDataEvent: TECOnOverPass = nil); overload;
procedure Tag(const SWLatitude, SWLongitude, NELatitude,NELongitude: double;
const tag_name: string = '';
const tag_value: string = '';
const data:TSetOSMData=[odNode,odWay];
const OnDataEvent: TECOnOverPass = nil); overload;
procedure Tag(const SWLatitude, SWLongitude, NELatitude,NELongitude: double;
const tags: array of string;
const Data:TSetOSMData=[odNode,odWay];
const Op: TBinaryFilterOSM = bfAnd;
const OnDataEvent: TECOnOverPass = nil); overload;
procedure Tag(const SWLatitude, SWLongitude, NELatitude,NELongitude: double;
const tag_name:string;
const tag_values: array of string;
const data:TSetOSMData=[odNode,odWay];
const Op: TBinaryFilterOSM = bfAnd;
const OnDataEvent: TECOnOverPass = nil); overload;
// search Way 'highway'='residential
map.OverPass.Tag('highway','residential',[odWay]);
// search Way 'highway'='residential' OR 'highway'='primary'
map.OverPass.Tag('highway',['residential','primary'],[odWay],bfOr);
//search Way width highway=residential AND name='Park Avenue'
map.OverPass.Tag(['highway','residential','name','Park Avenue'],[odWay],bfAnd);
Data retourne l'ensemble des données OSM disponibles pour la zone spécifiée
procedure Data(const SWLatitude,SWLongitude,NELatitude,NELongitude:double;const OnDataEvent:TECOnOverPass=nil); overload;
map.OverPassApi.data;
FilterPolygone vous permet d'utiliser un polygone pour limiter la zone de recherche
Vous pouvez par exemple utiliser un isoChrone
3// within 10 minutes walking distance
map.routing.IsoChrone.Time(map.latitude,map.longitude,map[ 'isochrone'].polygones,[10]) ;
if map['isochrone'].polygones.Count> 0 then
map.OverPassApi.FilterPolygone := map['isochrone'].polygones[0];
DemoNativeOverPassFiremonkey vous montre comment extraire des données de OpenStreetMap.
OSM XML est volumineux, certains fichiers font plusieurs Giga, TOSMFile peut utiliser un format interne (.olt) jusqu'a 19 fois plus léger, 10 fois plus rapide à traiter.
Pour convertir simplement un fichier .osm en .olt utiliser la procedure OSMFileToOLT(const OSMFilename:string;const Notify:TNOtifyEvent=nil);
La conversion est effectuée dans un thread et Notify est appelé lorsque le travail est terminé.
begin
// doEndSaveToOLT is call when file is saved
OSMFileToOLT(FOSMFile.filename, doEndSaveToOLT);
end;
procedure TForm2.doEndSaveToOLT(Sender : TObject);
begin
// here your osm file is savec in .olt
end;
Vous devez utiliser directement TOSMFile pour convertir des portions de fichiers OSM
2TOMSFile
function LoadFromFile(const sFilename
: string) : boolean;
function LoadFromStream(const OSMStream
: TStream) : boolean;
function LoadFromString(const OSMData :
string) : boolean;
property FilterPrimitive : TSetPrimitiveOSM ;
Il y a 3 primitives, les nodes, les ways et les relations.
FOSMFile.FilterPrimitive := [poNode,poWay,poRelation];
Si vous souhaitez connaitre simplement la zone geographique couverte par le fichier sans charger les données, filtrez tout !
4property FilterBounds : TFilterBounds;
Détermine les zones géographiques qui nous intéressent, les données situées en dehors sont ignorées.
FOSMFile.FilterBounds.Add(Area1_NorthEastLat, Area1_NorthEastLng, Area1_SouthWestLat, Area1_SouthWestLng);
FOSMFile.FilterBounds.Add(Area2_NorthEastLat, Area2_NorthEastLng, Area2_SouthWestLat, Area2_SouthWestLng);
property FilterNode : TListFilterOSM;
property FilterWay : TListFilterOSM;
property FilterRelation : TListFilterOSM;
Filtre les éléments en fonction de leur clefs et valeurs, les filtres descendent de la classe TFilterOSM
ExcludeKeyValue(const Key, Value : string), OnlyKeyValue(const Key, Value : string), ExcludeIfKeyExist(const Key:string) et OnlyIfKeyExist(const Key:string) vous simplifie la création de filtres.
3FOSMFile.FilterWay.ExcludeIfKeyExist('building');
FOSMFile.FilterWay.ExcludeKeyValue('leisure','park');
FOSMFile.FilterWay.ExcludeKeyValue('natural','coastline');
Retraite un fichier après avoir modifié les divers filtres, les clefs et les valeurs ne sont pas rechargées cela permet de gagnez quelques secondes.
procedure saveToFile(const Filename : string; NotifyEvent : TNotifyEvent = nil);
FOSMFile.SaveToFile('path_myfile.geojson');
// save in olt
FOSMFile.SaveToFile('path_myfile.olt');
Pour sauvegarder dans un thread indiquez un NotifyEvent
4begin
// doEndSaveToOLT is call when file is saved
FOSMFile.SaveToFile('path_myfile.olt',doEndSaveToOLT);
end;
procedure TForm2.doEndSaveToOLT(Sender : TObject);
begin
// here your osm file is savec in .olt
end;
property Ways : TWayList read FWayList;
property Relations : TRelationList read FRelationList;
Listes des éléments contenu dans le fichier après filtrage.
Chaque liste dispose de fonctions permettant d'effectuer des recherches sur ces éléments.
Find(idElement) retourne un élément en fonction de son id
Les diverses fonctions Search remplisse la liste SearchResult avec les éléments remplissant les conditions
function Search(const Lat, Lng, radiusKM : double) : integer; overload;Trouve tous les éléments situés dans une zone centrée sur le point Lat,Lng et de rayon radiusKM
function Search(const SWLat, SWLng, NELat, NELng : double) : integer; overload;
Trouve tous les éléments de la zone.
function Search(const SWLat, SWLng, NELat, NELng : double; const Key, Values : string) : integer; overload;
Trouve tous les éléments de la zone avec une Clef contenant les valeurs spécifiées.
function Search(const Key, Values : string) : integer; overload;
Trouve tous les éléments dont la clef contient les valeurs indiquées.
FOSMFile.Nodes.Search('amenity','cafe|bar|restaurant');
// search all ways with highway=residential or highway=secondary
FOSMFile.Ways.Search('highway','residential|secondary');
function Search(const Key : string) : integer; overload;
Trouve tous les éléments possédant cette clef, quelque soit la valeur.
procedure Clear;
procedure Abort;
Abandonne un chargement
procedure ToShapes(Shapes:TECShapes;NotifyEvent:TNotifyEvent=nil);
Charge les données dans un groupe.
FOSMFile.ToShapes(map.Shapes);
Charge les données recherchées dans un groupe.
FOSMFile.Nodes.Search('amenity','cafe|bar|restaurant');
// search all ways with highway=residential or highway=secondary
FOSMFile.Ways.Search('highway','residential|secondary');
// load in default group
FOSMFile.FindToShapes(map.Shapes);
function CountKey(Node: TBaseOSM):integer;
Retourne le nombre de tag pour un élément
function getKey(Node:TBaseOSM;const index:integer):string;
Retourne la key dont on passe l'index
function ReadKey(Node : TBaseOSM; const KeyName : string) : string; overload;
Retourne la valeur de la Key
function ReadKey(Node : TBaseOSM) : string; overload;
Retourne l'ensemble des paires key/value sous la forme : Key1=value1#13#10Key2=value2#13#10Keyx=ValueX
function ReadValuesForKey(const KeyName : string; valuesList : TStringList): integer;
Rempli ValuesList avec l'ensemble des valeurs pour une Key
property Aborted : boolean;
Indique si le chargement a été interrompu par Abort
property Bounds : TBoundsLatLng ;
Contient la zone géographique décrite par le fichier
property FileFormat: TFileTypeOSM;
Retourne le type de fichier (ftOSM ou ftOLT)
property Filename : string ;
property FileSize : int64;
property Keys : TUniqueStringList;
Liste de la totalité des Key du fichier
property Values : TUniqueStringList;
Liste de la totalité des Value du fichier
property Role[Member : TMemberOSM]:string;
property Timestamp : string ;
Retourne la date de la dernière mise à jour du fichier
property OnRead : TOnOSMBlockRead;
Pour pouvoir traiter des fichiers de plusieurs Giga la lecture est faite par bloc, cet événement est déclenché à chaque chargement d'un bloc.
property OnLoaded : TNotifyEvent;
Déclenché lorsque la totalité du fichier a été traité.
Consultez DemoOSMViewer pour voir une utilisation réelle de TOSMFile
2OSMViewer
Convertir un fichier OSM en OLT
Ouvrez le fichier OSM dans OSMviewer, la zone couverte s'affiche sur la carte
Cochez les primitives que vous souhaitez exporter (nodes, ways et relation) puis cliquez sur Save OLT pour lancer la conversion
Suivant la taille du fichier OSM le travail peut durer quelques minutes.
5Pour exporter les ways toutes les nodes sont
conservée en mémoire il faut avoir 1Mo de mémoire par
Go de fichier.
Si vous ne convertissez que les nodes vous pourrez
travailler avec des fichiers de 100 Go même si vous
n'avez que 8Mo de mémoire.
Une fois la zone chargée vous aurez le choix entre affichée les données sur la carte ou les sauvegarder en .olt
En chargeant les données vous pouvez effectuer des recherches en fonction des paires key/value
Vous pouvez télécharger un apk pour android d'une mini demo qui affiche les données OSM d'une petite zone.
Capture Image
Vous pouvez enregistrer la zone visible de l'écran avec la propriété ScreenShot qui est un TBitmap
// Delphi
map component TECNativeMap
// save map to bmp
file
map.Screenshot.SaveTofile('c:\mymap.bmp');
Vous pouvez aussi capturer n'importe quelle zone géographique, même hors-écran, avec la propriété ScreenShots
5// procedure
call when bitmap ready
map.ScreenShots.OnScreenShot := doScreenShot ;
// you can change the size of the
bitmap between each capture (default
800x600)
map.ScreenShots.Width := 2000;
map.ScreenShots.Height:= 2000;
// you can change
tileserver
map.ScreenShots.TileServer := tsOsmFr;
// capture area centered on a point
with a specified zoom
map.ScreenShots.ScreenShot(latitude,longiture,
16,'optional_name_of_capture');
// you can take screenshots even if
the previous is not over yet
// Take the best zoom to a specific
area
map.ScreenShots.ScreenShot(NorthEastLat, NorthEastELng,
SouthWestWLat, SouthWestLng,'optional_name_of_capture');
// Take the best zoom to an area
defined by its center and radius in km
// CAUTION use double for the
radius, here 1.0 km, otherwise it will be mistaken for a
simple zoom
map.ScreenShots.ScreenShot(Latitude, Longitude,
1.0 ,'optional_name_of_capture');
// when capture is ready, you go
here
procedure
TForm.doScreenShot(const
name:string;const Screenshot:TBitmap);
begin
// don't free ScreenShot
!
screenshot.SaveToFile(YourPath+name+'.bmp');
end;
La demo Photographer pour Firemonkey vous montre un exemple d'utilisation, vous lancez 8 "drones" pour photographier le terrain tous les x mètres.