Pour utiliser les formes vous devez rajouter l'unité uecNativeShape
Tous les éléments positionnés sur la carte sont accessibles au travers de la propriété Shapes de type TECShapes ou des autres groupes via Group['name'], ils descendent tous de la classe TECShape
Vous pouvez stockers dans vos éléments (marker, poi, line ou polygone) les données textuelles que souhaitez au travers de la propriété PropertyValue ses valeurs pourront être associées à un style
...
M := Map.addMarker(map.latitude,map.Longitude);
M.PropertyValue['my_tag']:='value_tag';
// you can also use
M['my_tag']:='value_tag';
// groups can also have them
map.shapes['tag']:='value';
map['group']['tag']:='value';
Lorsque vous ajoutez plusieurs éléments à la suite encadrez-les par le couple BeginUpdate / EndUpdate
1Styles
Au lieu de décorer manuellement chaque élément vous pouvez définir des régles pour leur appliquer un style
Groupes ( TECShapes )
Un groupe gère un ensemble d'éléments, en fait la propriété Shapes est le groupe par défaut, vous accédez à un groupe par la propriété Group['name']
Vous pouvez aussi y accéder par un index au travers de la propriété Groups
1var
my_group:TECShapes;
// for optimisation
my_group := map.Group['group1'];
my_group.BeginUpdate;
my_group.Markers.add(lat1,lng1);
my_group.Markers.add(lat2,lng2);
...
my_group.EndUpdate;
Les propriétés Pois, markers, lines et Polygones disposent aussi d'une procedure fitBounds
2L'événement OnLoad est déclenché lorsque le contenu est totalement disponible
3Charge le groupe avec un stream contenant des données au format OSM XML ou olt
Charge le groupe avec une chaine contenant des données au format OSM XML ou olt
Active les support des Clusters, cela permet de regrouper des markers ou des pois proches pour une meilleure visibilité
property Pois: TECShapePOIList
Les listes d'éléments disposent d'un itérateur comme les groupes
2var
my_group:TECShapes;
// for optimisation
my_group := map.Group['group1'];
my_group.BeginUpdate;
my_group.Markers.add(lat1,lng1);
my_group.Markers.add(lat2,lng2);
...
my_group.EndUpdate;
Vous avez aussi des raccourcis pour créer vos éléments
3function addMarker(const Lat, Lng: double) : TECShapeMarker;
function AddPOI(const Lat, Lng: double) : TECShapePOI;
function AddLine: TECShapeLine;
function AddEncodedLine(const EncodedLine: string; const precision: byte = 5): TECShapeLine;
function AddLine(const dLatLngs: array of double): TECShapeLine;
function AddLine(const dLine: TECShapeLine) : TECShapeLine;
function AddPolygone : TECShapePolygone;
function AddPolygone(const dLine: TECShapeLine): TECShapePolygone;
function AddEncodedPolygone(const EncodedLine: string; const precision: byte = 5): TECShapePolygone;
function AddPolygone(const dLatLngs: array of double): TECShapePolygone;
...
M := Map.addMarker(map.latitude,map.Longitude);
M.PropertyValue['my_tag']:='value_tag';
// you can also use
M['my_tag']:='value_tag';
// groups can also have them
map.shapes['tag']:='value';
map['group']['tag']:='value';
property MaxZoom: byte
L'opacité varie de 0 à 100, une valeur >100 indique que l'opacité du groupe n'est pas prise en compte et que seule celle des éléménts est utilisée.
Dans le cas d'une valeur > 100, l'opacité originelle des éléments n'est pas restaurée
1TECNativeMap.TopGroupZindex retourne le ZIndex le plus élevé de tous les groupes
4Les éléments ont eux aussi une propriété clickable
5Ne s'applique pas si l'on sauvegarde directement le groupe
6var
my_group:TECShapes;
// for optimisation
my_group := map.Group['group1'];
my_group.BeginUpdate;
my_group.Markers.add(lat1,lng1);
my_group.Markers.add(lat2,lng2);
...
my_group.EndUpdate;
Retourne true si au moins un des éléments du groupe est sélectionné.
Les listes d'éléments ont aussi une propriété Selected
7...
M := Map.addMarker(map.latitude,map.Longitude);
M.PropertyValue['my_tag']:='value_tag';
// you can also use
M['my_tag']:='value_tag';
// groups can also have them
map.shapes['tag']:='value';
map['group']['tag']:='value';
property Name: string
CSV
Le gestionnaire de fichiers CSV est accessible au travers de la propriété CSV des groupes
function LoadFromFile(const filename: string):boolean;Lorsque les données sont chargées l'événement OnLoad de la carte est déclenché
8procedure SaveToFile(const filename: string;const ShapeList:TECShapeList);
Enregistre la liste d'éléments (markers ou Pois) dans un fichier csv
Utilisez la liste Fields pour sélectionner les PropertyValue a enregistrer.Fields contient les champs du dernier fichier CSV chargé donc au besoin videz la avant de la remplir avec votre sélection.
Pas besoin d'y rajouter les champs pour la Latitude et Longitude, FieldNameLatitude et FieldNameLongitude seront utilisées
...
M := Map.addMarker(map.latitude,map.Longitude);
M.PropertyValue['my_tag']:='value_tag';
// you can also use
M['my_tag']:='value_tag';
// groups can also have them
map.shapes['tag']:='value';
map['group']['tag']:='value';
property FieldNameWKT: string;
// save the geometry of elements in WKT format, essential for lines and polygons.
// for this you must fill in the field FieldNameWKT
map.shapes.csv.FieldNameWKT := 'WKT';
map['group'].csv.FieldNameWKT := 'WKT';
map.shapes.savetofile('filename.csv');
map['group'].savetofile('filename.csv');
property FieldNameLatitude: string;
Si la position géographique est regroupée dans un seul champ, indiquez le dans FieldNameLatitude, laissez FieldNameLongitude vide, utilisez DelimiterLatLng pour définir le séparateur entre la latitude et la longitude.
4map.Shapes.CSV.FieldNameLongitude := '';
map.Shapes.CSV.DelimiterLatLng := ',';
property idxLatitude: integer
property idxLongitude: integer
// you can indicate directly the index of the fields containing the latitude and longitude
// You must also empty FieldNameLatitude and FieldNameLongitude
map.Shapes.CSV.FieldNameLatitude := '';
map.Shapes.CSV.FieldNameLongitude := '';
map.Shapes.CSV.idxLatitude := 10;
map.Shapes.CSV.idxLongitude := 11;
property Delimiter : char
map.shapes.CSV.OnFilterCSV := doOnFilterCSV;
...
// valid csv data , default true
procedure TForm.doOnFilterCSV(const Data: TStringList;var validCSV:boolean);
begin
if (data.Count>2) and (pos('POLYGON',data[7])< 1) then
validCSV := (data[2]<>'relation');
end;
property OnCreateCSVPoint: TOnCreateCSVPoint
map.shapes.CSV.OnCreateCSVPoint := doOnCreateCSVPoint;
...
// Manual creation of each point
// Data contains the CSV values for the point
procedure TForm.doOnCreateCSVPoint(const Group: TECShapes; var CSVPoint: TECShape; const Lat, Lng: double; const Data:TStringList) ;
var M:TECShapeMarker;
begin
// create new marker
M := Group.addMarker(lat,lng);;
CSVPoint := M ;
// marker design
M.Width := 12;
M.StyleIcon := siFlat;
// we calculate its color according to its index number
M.Color := GetHashColor(inttostr(M.IndexOf));
end;
property OnCreateWKTObject : TOnCreateWKTObject
map.shapes.CSV.OnCreateWKTObject := doOnCreateWKTObject;
map['group'].CSV.OnCreateWKTObject := doOnCreateWKTObject;
// fired after creation wkt object
procedure TForm.doOnCreateWKTObject(const Group: TECShapes;
const WKTObject: TECShape; const Lat, Lng: double; const Data: TStringList);
begin
// we calculate its color according to its index number
if WKTObject is TECShapePolygone then
TECShapePolygone(WKTObject).FillColor := GetHashColor(inttostr(WKTObject.IndexOf))
else
WKTObject.Color := GetHashColor(inttostr(WKTObject.IndexOf));
end;
La géométrie doit être exprimée en degrès décimal, si besoin vous pouvez vous brancher sur OnConvertLatLng pour définir une procédure de conversion
1// you can connect to OnConvertLatLng to convert
// sample
procedure ConvertLatLng(var lat,lng:double);
begin
Lat := Lat / 1000000;
Lng := Lng / 1000000;
end;
procedure TForm.FormCreate(Sender: TObject);
begin
map.shapes.CSV.OnConvertLatLng := ConvertLatLng;
end;
Les autres champs du fichier CSV sont importés dans
les éléments au travers de leur propriété
PropertyValue[field_name] := field_value
Si le fichier CSV ne nomme pas ses champs, ils seront
dénommés en concatant le nom du fichier sans l'extension
+ l'index du champ
Labels
Les listes de Polygones, de Markers et de Pois permettent d'associer des labels à leurs éléments, vous y accédez au travers de la propriétés Labels
property Align: TLabelShapeAlignproperty BorderColor: TColor
property ColorType: TLabelShapeColorType
property FontColor: TColor
property FontBold: boolean
property FontItalic: boolean
property FontSize: integer
property FontFamily: string
property LabelType: TLabelShapeType
nombre de décimales utilisées pour l'affichage des latitude et longitude, par défaut 3
Mettre 0 (valeur par défaut) pour que tout le texte s'affiche
property ShowOnlyIf : TLabelShowOnly (default lsoAll)
Filtrer l'affichage des labels
Possibilités : lsoAll,lsoSelected,lsoPressed,lsoHover,lsoFocused
...
M := Map.addMarker(map.latitude,map.Longitude);
M.PropertyValue['my_tag']:='value_tag';
// you can also use
M['my_tag']:='value_tag';
// groups can also have them
map.shapes['tag']:='value';
map['group']['tag']:='value';
sur mobile lsoHover est identique à lsoPressed
9...
M := Map.addMarker(map.latitude,map.Longitude);
M.PropertyValue['my_tag']:='value_tag';
// you can also use
M['my_tag']:='value_tag';
// groups can also have them
map.shapes['tag']:='value';
map['group']['tag']:='value';
Ajouter des Shapes
Vous pouvez utiliser les raccourcis suivant pour ajouter vos éléments
function TNativeMapControl.AddPOI(const Lat, Lng: double; const GroupName: string = ''): TECShapePOI;
function TNativeMapControl.AddMarker(const Lat, Lng: double; const GroupName: string = ''): TECShapeMarker;
function TNativeMapControl.AddLine(const Lat, Lng: double; const GroupName: string = ''): TECShapeLine;
...
M := Map.addMarker(map.latitude,map.Longitude);
M.PropertyValue['my_tag']:='value_tag';
// you can also use
M['my_tag']:='value_tag';
// groups can also have them
map.shapes['tag']:='value';
map['group']['tag']:='value';
function TNativeMapControl.AddLine(const dLatLngs: array of double; const GroupName: string = ''): TECShapeLine;
...
M := Map.addMarker(map.latitude,map.Longitude);
M.PropertyValue['my_tag']:='value_tag';
// you can also use
M['my_tag']:='value_tag';
// groups can also have them
map.shapes['tag']:='value';
map['group']['tag']:='value';
function TNativeMapControl.AddPolygone(const Lat, Lng: double; const GroupName: string = ''): TECShapePolygone;
function TNativeMapControl.AddPolygone(const dLatLngs: array of double; const GroupName: string = ''): TECShapePolygone;
function TNativeMapControl.AddInfoWindow(const Lat, Lng: double; const GroupName: string = ''): TECShapeInfoWindow;
Vous ne devez pas détruire manuellement les éléments ainsi créé si besoin utilisez remove, ils sont maintenu dans les listes de leur groupe respectif
2TECClusterManager
Les propriétés suivantes vous permettent de modifier l'affichage des clusters
property Color : TColorproperty Style : TClusterStyle (csEllipse, csStar, csRect, csTriangle, csHexagon, csDiamond)
property TextColor : TColor
property BorderColor : TColor
property BorderSize : integer
property FontSize : integer
property Opacity : byte
property WidthHeight : integer
property FillClusterList : boolean
Vous pourrez y avoir accès dans l'événement OnMouseOverCluster ( Cluster.shapes )
Les éléments qui sont à moins de MaxPixelDistance d'un cluster y sont regroupés, 60 pixels par défaut
Permet d'afficher les clusters pendant que l'on déplace la carte, par défaut true
Si le zoom est superieur à MaxZoom on ne regroupe pas les éléments, defaut 18
Déclenché lors de l'ajout d'un élément dans un cluster, vous pouvez refuser en basculant cancel à true, défaut false
var Color:TColor;var BorderColor:TColor;var TextColor:TColor,
var WidthHeight,FontSize:integer;var CStyle:TClusterStyle)
Déclenché avant l'affichage pour vous permettre d'ajuster les propriétés
Si vous vous branchez sur cet évenement vous prenez en charge intégralement le dessin du cluster
Déclenché par l'entrée de la souris sur le cluster
Déclenché par la sortie de la souris du cluster
exemple, changer la couleur en fonction du nombre d'éléments contenu par le cluster
// if you need to manipulate the elements contained in the cluster set FillClusterList a true
map.Shapes.ClusterManager.FillClusterList := true;
map.Shapes.ClusterManager.OnColorSizeCluster := doOnColorSizeCluster;
procedure TForm.doOnColorSizeCluster(const Cluster : TECCluster;
var Color:TColor;var BorderColor:TColor;var TextColor:TColor;
var WidthHeight,FontSize:integer;
var CCluster : TClusterStyle
);
//var i, nbrSelected: integer;
begin
// sample code if you need to manipulate the elements contained in the cluster
(*
nbrSelected := 0;
for i := 0 to Cluster.shapes.count - 1 do
begin
if Cluster.shapes[i].selected then
inc(nbrSelected);
end;
*)
if Cluster.Count< 10 then
begin
Color := clGreen;
end
else
if Cluster.Count< 100 then
begin
Color := clBlue;
end
else
Color := clRed;
end;
Élément TECShape
Tous les éléments affichable descendent de TECShape, ils partagent les propriétés suivantes
property Clusterable : booleanPermet d'exclure l'élement des clusters, par défaut true
Geolocalise l'élément, équivalent Address mais n'est pas bloquante
Déclenche OnShapeLocation(item:TECShape,GeoResult:TECGeoResult;const Valid:boolean);
Si le TECShape n'a pas d'événement OnShapeLocation c'est le OnShapeLocation de son groupe qui est déclenché.
Valid est a true si la position actuelle de l'élément est la même que celle lors du déclenchement de la recherche.
// you can
use Iterator
var shape:TECShape
for shape in map.Selected
do
begin
..
end;
function DistanceTo(Shape:TECShape)
Si TrackLine est définie la trace du déplacement de l'élément sera automatique gérée
Pour l'activer il suffit simplement d'y accéder, vous pouvez aussi directement assigner une ligne
// To activate the trace just access TrackLine
// line is created in the same group as FTracker
FTracker.TrackLine.visible := true;
// You can also pass a line
FTracker.TrackLine := your_line;
// for stop tracking set to nil , the line is free
FTracker.TrackLine := nil
Si vous testez directement TrackLine elle est automatiquement créé si elle n'existe pas !
10Force l'élément a s'afficher au premier plan sans tenir compte des zindex
Un seul élément à la fois peut-être au premier plan, BringToFront ne change pas l'ordre d'affichage qui reste dépendant du ZIndex
11En basculant la propriété TNativeMapControl.ShapeDragMode sur sdmMultiShapes (défaut sdmShape) et si l'élément pointé par la souris est sélectionné vous pourrez déplacer simultanément tous les éléments draggable sélectionnés, ils garderont les mêmes distances entre eux.
property AngleDisponible pour les TECShapeMarker et TECShapePOI
3Le texte peut être enrichi avec certains balises html voir TECShapeInfoWindow
5Vous pouvez utilisez PropertyValue pour stocker vos propres données, cette propriété est aussi utilisée par les tuiles vectorielles, les données OpenStreetMap y sont sauvegardées.
12Sélectionne ou non un élément, un élément sélectionné s'affiche comme s'il était survolé
La propriété Selected de la carte contient tous les éléments sélectionnés// you can
use Iterator
var shape:TECShape
for shape in map.Selected
do
begin
..
end;
TECSelectedShapesList
Type de la liste des éléments sélectionnés, vous donne accès àfunction ByArea(const NEALat,NEALng,SWALat,SWALng :double):integer;
function count : integer;
procedure SaveToFile(const filename:string);
property Item[index: integer]: TECShapeRecherche
Vous avez plusieurs fonctions pour effectuer des recherches dans vos éléments
function FindShapeByArea(const SWALat, SWALng, NEALat, NEALng: double; const ShapeList: TList<TECShape>; const FilterShapes : TNativeShapes = []; Filter:TOnShapeFilter=nil): integer;
Rempli ShapeList avec les éléments se trouvant dans une zone rectangulaire dont on indique les coins Sud-Ouest et Nord-Est
FilterShapes permet de filtrer les éléments recherchés, par défaut tous, exemple [nsMarker,nsPoi] pour ne rechercher que des TECShapeMarker et TECShapePOI
Filter permet d'ajouter une procedure pour filtrer la recherche
map.FindShapeByKMDistance(map.Latitude,map.Longitude, 2.0,liste,[nsMarker,nsPoi],FilterCafe);
...
procedure FilterCafe(const Shape: TECShape; var cancel: boolean);
begin
cancel := shape.PropertyValue['kind']<>'cafe' ;
end;
function FindShapeByKMDistance(const FLat, FLng, FKMDistance: double; const ShapeList: TList<TECShape>; const FilterShapes : TNativeShapes = []; Filter:TOnShapeFilter=nil): integer;
function FindShapeByFilter(const ShapeList: TList<TECShape>; const FilterShapes : TNativeShapes; Filter:TOnShapeFilter): integer;
Toutes ces fonctions retournent le nombre d'éléments trouvé.
13Pour les versions de Delphi qui ne supportent pas les génériques ShapeList est une simple TList
14Événements
Les formes déclenchent les événements suivant :
property OnShapeMove : TOnShapeMove
property OnShapeDrag : TOnShapeMove
property OnShapeDragEnd : TNotifyEvent
property OnShapeMouseOver : TOnShapeMouseEvent
property OnShapeMouseOut : TOnShapeMouseEvent
property OnShapeMouseDown : TOnShapeMouseEvent
property OnShapeMouseup : TOnShapeMouseEvent
property OnShapeClick : TOnShapeMouseEvent
property OnShapeRightClick: TOnShapeMouseEvent
property OnShapeDblClick : TOnShapeMouseEvent
property OnShapePathChange : TNotifyEvent
property OnShapeLocation : TOnShapeLocation
Les événements peuvent être attribués individuellement à chaque élément, dans ce cas ils ne sont pas répercutés au niveau de TECNativeMap
6Aimanter des markers sur une ligne ou un polygone
Vous pouver définir des TECShapeMarker et des TECShapePOI qui seront automatiquement attirés vers une TECShapeLine ou un TECShapePolygone si vous les lachez a une certaine distance de ceux-ci.
Vous gérer cela au travers de la propriété SnapDrag de type TECSnapDrag du composant cartographique TECNativeMap.
function AddMarker(const Marker: TECShape): boolean;
retourne true si l'élément est bien ajouté.
retourne true si l'élément est bien ajouté.
true pour des metres , false (defaut) pour des pixels.
map.SnapDrag.AddGuide(poly);
map.SnapDrag.AddGuide(red_line);
map.SnapDrag.MeterDistance := true;
map.SnapDrag.SnapDistance := 50; // 50 meters
map.SnapDrag.MeterDistance := false;
map.SnapDrag.SnapDistance := 50; // 50 pixels
La propriété _snap_ des guides est mise à true lorsqu'elle attire un marker, vous pouvez vous en servir pour définir un style qui signalera visuellement cet état.
7map.Styles.addRule('.line._snap_:true {scale:2}') ;
map.Styles.addRule('.polygone._snap_:true {scale:2}') ;
// default size
map.Styles.addRule('.line._snap_:false {scale:1}') ;
map.Styles.addRule('.polygone._snap_:false {scale:1}') ;
// doted target line
map.Styles.addRule('#TECSnapDrag.line{penStyle:Dot}');
Si vous souhaitez que des markers soient attirés par des lignes particulières, vous pouvez créer votre propre variable de type TECSnapeDrag
8...
MySnapDrag := TECSnapDrag.create;
MySnapDrag.addMarker(mrk);
MySnapDrag.AddGuide(poly);
MySnapDrag.AddGuide(red_line);
...
MySnapDrag.free
Dessin et sélection main libre
FreeHand vous permet de définir des lignes, qui pourront devenir des polygones, à main lever, pour cela il suffit d'activer FreeHand.Draw
map.FreeHand.OnDraw := doFreeHandDraw;
// activate the hands-free drawing
map.FreeHand.Draw := true;
...
procedure TForm.doFreeHandDraw(Sender: TObject);
begin
// save the line to your map
map.addLine(TECNativeFreeHand(sender).line)
// you can use also this syntax
map.FreeHand.addLine;
// convert the drawn line into a polygon and add it to the map
map.addPolygone(TECNativeFreeHand(sender).line);
// you can use also this syntax
map.freeHand.addPolygone;
end;
Vous pouvez aussi activer l'outil de sélection main libre, cela vous permet de choisir des éléments simplement en les entourant
property AutomaticMapMovement : boolean ;
Autorise le déplacement automatique de la carte lorsque le curseur de dessin approche d'un bord, défaut True.
property Draw: boolean ;
Active le mode dessin
property Selection: boolean ;
Active le mode Selection
Ne désactivez pas Draw après avoir activé Selection, Selection active aussi Draw !
4property MouseButton: TMouseButton ;
Bouton de la souris utilisé pour dessiner, par defaut mbRight
Si vous utilisez le bouton gauche, il carte pourra être déplacée en maintenant la touche CTRL enfoncée.
9property Cursor: TECShape ;
Curseur de dessin, par défaut un TECShapePOI en forme de croix
property Line: TECShapeLine;
La ligne qui représente votre dessin, vous pouvez ajuster ses propriétés soit directement soit par un style.
map.Styles.addRule('#TECNativeFreeHand.Line {color : green;penStyle:Dash;weight:2}') ;
property PolygoneSelection: TECShapePolygone ;
Accessible dans l'événenement OnSelection, il représente l'aire de votre sélection
property SelectionList: TECShapesList;
Accessible dans l'événement OnSelection, cette liste contient les éléments sélectionnés
map.FreeHand.OnPermission := doOnFreeHandPermission;
...
// selection with freeHand is only allowed if CTRL or SHIFT is pressed
procedure TForm1.doOnFreeHandPermission(sender : TObject;var valid:boolean);
begin
valid := (((GetKeyState(VK_CONTROL) and $8000) = $8000) or
((GetKeyState(VK_SHIFT) and $8000) = $8000)
);
end;
property SelectionFilter: TOnShapeFilter
Permet de définir un filtre pour la sélection
...
// select only cafe
procedure FilterCafe(const Shape: TECShape; var cancel: boolean);
begin
cancel := shape.PropertyValue['kind']<>'cafe' ;
end;
function AddLine(const GroupName:string=''):TECShapeLine;
function AddPolygone(const GroupName:string=''):TECShapePolygone;
SelectArea
Cette propriété permet de sélectionner une zone rectangulaire ou circulaire.
property AreaType: TECAreaType ;
property Area: double
property Width: double
property Height: double
property Color : TColor
procedure setPosition(const Lat,Lng:double)
procedure Boundary(const dNELat, dNELng, dSWLat, dSWLng: double)
procedure fitBounds
property Center : TLatLng
property NELat: double
property NELng: double
property SWLat: double
property SWLng: double
property Visible: boolean
property ShowMetrics : boolean
property OnChange: TNotifyEvent
property OnClick: TNotifyEvent
property OnDblClick: TNotifyEvent
property OnLongPress: TNotifyEvent
property OnRightClick: TNotifyEvent
property OnUpdateMetric : TOnUpdateMetric
begin
map.SelectArea.OnChange := doOnChange;
map.SelectArea.OnUpdateMetric:= doUpdateMetric;
map.SelectArea.Visible := true;
end;
procedure TFSelectArea.doUpdateMetric(const sender: TECSelectArea; var Value: string);
begin
// display only area
value := 'Area : '+doubletostrdigit(map.SelectArea.Area, 3)+' Km²';
end;
procedure TFSelectArea.doOnChange(sender : TObject);
begin
case map.SelectArea.AreaType of
atRectangle: begin
info.Caption := 'NorthEst : '+ doubletostrdigit(map.SelectArea.NELat,3)+','+
doubletostrdigit(map.SelectArea.NELng,3)+' SouthWest : '+
doubletostrdigit(map.SelectArea.SWLat,3)+','+
doubletostrdigit(map.SelectArea.SWLng,3)+
' W : '+doubletostrdigit(map.SelectArea.Width, 2)+' Km '+
'H : '+doubletostrdigit(map.SelectArea.Height, 2)+' Km '+
'Area : '+doubletostrdigit(map.SelectArea.Area, 3)+' Km²';
end;
atCircle: begin
info.Caption := 'Lat : '+ doubletostrdigit(map.SelectArea.Center.lat,3)+','+
doubletostrdigit(map.SelectArea.Center.lng,3)+' Radius : '+
doubletostrdigit(map.SelectArea.Width / 2,2)+' Km Area : '+doubletostrdigit(map.SelectArea.Area, 3)+' Km²';
end;
end;
end;