TECShapeLine vous permet de tracer une ligne constituée d'un ensemble de points sur votre carte.
Les lignes sont gérés par une liste de type TECShapeLines accessible au travers de la propriété Lines des groupes TECShapes
Cette propriétés dispose d'une fonction qui vous permet de trouver la lignes la plus proche d'un point particulier.
nl := map.shapes.lines.NearestLineToPoint(lat,lng);
/// nl.line is the closest line to lat,lng position
if assigned(nl.line) then
begin
nl.lat; // latitude on line
nl.lng; // longitude on line
nl.distance; // distance to line in meters
end;
TECShapeline
Cette classe descend de TECShape
Elle possède en plus les propriétés suivantes
function Add(const Lat, Lng: double; const Alt: double = _ErrorAltitude): integer;
Contrairement à l'ajout d'un simple point, vous n'avez pas besoin d'encadrer l'ajout de votre tableau par BeginUpdate / EndUpdate, cela est fait automatiquement.
1Inverse le sens de la ligne
property ShowDirection : boolean
Ajoute des flêches à chaque segment pour montrer la direction
procedure Slice(ALat,ALng,BLat,BLng:double;Line: TECShapeLine);
Si ces points ne sont pas sur la ligne, ils sont remplacés par les points les plus proches situés sur le ligne
Si ces points ne sont pas sur la ligne, ils sont remplacés par les points les plus proches situés sur le ligne
Copier dans Line la partie délimité par les segments StartIndex et EndIndex
function Slice(const StartIndex,EndIndex:integer;GroupName:string=''):TECShapeLine;
Retourne une ligne composée de la portion délimité par les segments StartIndex et EndIndex
procedure Slice(const StartKm,EndKm : double;Line : TECShapeLine);
Copier dans Line la partie débutant au kilomètre StartKM et finissant au kilomètre EndKM
function Slice(const StartKm,EndKm : double;GroupName:string=''):TECShapeLine;
Retourne une ligne composée de la portion débutant au kilomètre StartKM et finissant au kilomètre EndKM
if map.shapes.lines.count>0 then
begin
redLine := map.shapes.lines[0].slice(1.2,3.8);
redLine.color := clRed;
end;
// also
map['group_name'].lines.count> 0 then
map['group_name'].lines[0].slice(1.2,3.8).color := clRed;
procedure Clear;
property Encoded: string ;
property EncodePrecision: byte;
procedure Delete(index: integer);
En utilisant psUserStyle et setCustomDash([len_dash,len_space,..,len_dashx,len_spacex]) vous pouvez créer votre schéma de traits
line.SetCustomDash([4,4,2,4,4,4]);
//you can use in styles like this
map.styles.addRule('#_DRAGZOOM_.line {weight:4;color:green;penStyle:userStyle;customStyle:4,4,2,4,4,4}');
Vous pouvez animer les traits.
property LineType : TECLineType
ltStraight Relier les points sans afficher ceux-ci (défaut)
ltBezier Tracer des courbes de bézier entre les points
ltDot Afficher les points sans les relier entre eux
ltDotLine Afficher les points et les relier entre eux (equivalant à ltDot + ltStraight)
Calcule les altitudes des points, vous pouvez lui passer une procédure de type TOnGetAltitude pour pouvoir afficher une barre de progression (voir DemoNativeRoute)
// Delphi
map component ECMap
// calcul altitude for all point
of polyline 0
// you can pass nil if you don't
show a progressbar
map.Shapes.Lines[0].GetAltitudes(doGetAltitude);
...
{*
event fired by getAltitudes
@param Sender TECShapeLine
@param Total number of altitude's point
calculated
@cancel flag for abort calcul
}
procedure
TFDemoRoute.doOnGetAltitude(Sender:
TECShapeLine;const
Total:integer;var
cancel:boolean);
begin
ProgressAltitude.Position := total;
// cancel if press
button
cancel := btAbortAlt.tag = -1;
end;
const lMeter: longint; var dLatitude, dLongitude: double;
var idPoint: integer; var Heading: integer; var bEnd: boolean): boolean;
Calcule la latitude et la longitude d'un point sur la line/polygone en fonction de sa distance en mètres, retourne True si on a trouvé un point
SensStartEnd sens du parcours, true pour départ -> arrivée
lMeter la distance en mètredLatitude,dLongitude des variables de type double qui recevront la latitude et la longitude
idPoint une variable qui contiendra l'indice dans le tableau Path où se situe le point, le calcul retourne une approximation car votre polyline/polygone ne comporte par l'ensemble des points réels
Heading une variable qui contiendra l'angle du point par rapport au nord (de 0 à 360°)
bEnd indique si l'on a atteind ou dépassé la fin du polyline/polygone(ou le début suivant le sens)
Tableau contenant l'ensemble des points de la ligne
public
property Latitude: double ;
property Longitude: double ;
property Alt: double ;
property Distance: integer ; // meters
property Text: string ;
property Time: TDateTime ;
property Maneuver: string ;
property item: TObject ;
end;
Vous pouvez y accéder directement avec line[index] au lieu de line.Path[index]
1Retourne la distance entre 2 points géographique situés sur la ligne.
Si les points ne sont pas sur la ligne, ils sont remplacés par les 2 points de la ligne les plus proches.
Retourne la distance du départ jusqu'au point géographique situé sur la ligne.
Si le point n'est pas sur la ligne, il est remplacé par le point de la ligne le plus proche.
// Delphi
map component TECNativeMap
line := map.Shapes.Lines[0];
// show the entire
line
map.fitBounds(line.NorthEastLatitude,line.NorthEastLongitude,line.SouthWestLatitude,line.SouthWestLongitude);
Si la ligne représente une route donne accès aux formes qui signalent les étapes
Les points de départ et d'arrivée sont représentés par des TECShapePOI, les autres points intermédiaires sont des TECShapeMarker
L'exemple ci-dessous permet de modifier l'affichage des points de départ et d'arrivée.
// Delphi
map component TECNativeMap
// change default poi start and
finish of route
var line :
TECShapeLine;
...
line := map.shapes.lines[0];
if
line.shapes.Pois.count>1
then
begin
i :=
line.shapes.markers.add(line.shapes.pois[0].latitude,line.shapes.pois[
0].longitude);
line.shapes.markers[i].filename := 'http://www.helpandweb.com/flag_blue.png';
line.shapes.markers[i].hint :=
line.shapes.pois[0].hint;
i :=
line.shapes.markers.add(line.shapes.pois[line.shapes.Pois.count-
1].latitude,line.shapes.pois[line.shapes.Pois.count-
1].longitude);
line.shapes.markers[i].XAnchor := 0;
line.shapes.markers[i].filename := 'http://www.helpandweb.com/checkered_flag.png';
line.shapes.markers[i].hint :=
line.shapes.pois[line.shapes.Pois.count-1].hint;
// hide default start and
finish
line.shapes.pois[0].visible
:= false;
line.shapes.pois[line.shapes.Pois.count-1].visible := false;
end;
Mode édition
property Editable : booleanUtilisez la propriété
EditShadowLine de votre carte pour
cacher ou modifier la trace de la future ligne.
La carte possède aussi une propriété
EditShape de type TECShape qui
contient l'élément en cours d'édition.
// hide shadow line
Map.EditShadowLine.visible := false;
// you can also use style for this line
Map.Styles.addRule('#_EDIT_SHADOW_LINE_ {color:red;penStyle:dot}');
// Add or Edit a line when clicking on the map
procedure TForm.MapClick(sender: TObject; const Lat, Lng: Double);
var Line : TECShapeLine;
begin
if (map.editshape is TECShapeLine) then
// if a line is already in edition mode it is used
Line := TECShapeLine(map.editshape)
else
// otherwise we create a new line and put it in edit mode
begin
line := map.addLine;
line.OnShapePathChange := OnPathChangeLine;
line.OnDblClickEditLine := DblClickEditLine;
line.OnChangeEditable := OnEditableLine;
line.editable := true;
end;
// add new point
line.Add(lat,lng);
end;
// triggered when adding, deleting or moving a point in the line
procedure Tform.OnPathChangeLine(Sender: TObject);
var
line : TECShapeLine;
begin
line := TECShapeLine(Sender);
// Use PathChange to find out the type of change
// Use PathIndexChange to determine the index of the modified point
case line.PathChange of
pcDelete: caption := 'delete' ;
pcAdd: caption := 'add';
pcMove: caption := 'move' ;
end;
end;
// Triggered by a double click on the line in edit mode
procedure TForm.OnDblClickEditLine(sender: TECShape; const IndexPoint: integer;
const NewLat, NewLng: double; var cancel: boolean);
begin
// do not delete the first and the last points
if (TECShapeLine(sender).PathChange=pcDelete) then
cancel := (IndexPoint=0) or (IndexPoint=TECShapeLine(sender).count-1);
end;
// Triggered when changing the editable mode
procedure TForm.OnEditableLine(sender:TObject);
begin
if TECShapeLine(sender).editable then
showmessage('start edit')
else
showmessage('end edit');
end;
Cela ne permet que des tracés rectilignes, pour
modifier une route
cela demande juste 2-3 lignes de codes
supplémentaires.
Vous pouvez aussi définir un tracé à main
levée.
Par défaut les points de sélection sont représentés par un carré noir pour le point de départ, un carré blanc pour le point final et un rond blanc pour les points intermédiaires.
Utilisez les propriétés FilenameStartEditLine, FilenameEndEditLine, FilenamePointEditLine de votre carte pour changer les bitmaps
s := map.FilenameStartEditLine;
map.FilenameStartEditLine := map.FilenameEndEditLine;
map.FilenameEndEditLine := s;
Vous pouvez prendre en charge la création des points de sélection en utilisant la propriété OnCreateShapeLinePoint
line :=
map.add(nsLine,Lat,Lng);
// change défault
point
line.OnCreateShapeLinePoint :=
doCreateShapeLinePointEditable;
procedure
TForm1.doCreateShapeLinePointEditable(sender: TObject;
const Group:TECShapes;
var ShapeLinePoint:
TECShape;
const
Lat,Lng:double;const
index:integer);
var i:integer;
poi:TECShapePOI;
begin
i := Group.Pois.add(lat,Lng);
Poi := Group.Pois[i];
ShapeLinePoint := poi;
poi.Width := 10;
poi.Height:= 10;
poi.POIShape := poiRect;
poi.Color := claWhite;
poi.HoverColor := claWhite;
poi.BorderColor := claBlack;
poi.HoverBorderColor:= claBlack;
end;
property OnShapePathChange : TNotifyEvent
Sélectionner une portion de la ligne
Pour pouvoir sélectionner une portion de votre ligne à la souris ou par code, utilisez la classe TecNativeLineSelect (unité uecEditNativeLine)
...
SelectLine := TecNativeLineSelect.create;
// triggered by selection
SelectLine.OnSelect := doSelect;
// triggered by deselection
SelectLine.OnDeselect := doDeselect;
SelectLine.Line := your_Line;
Survolez la ligne et cliquez sur le point de sélection pour le valider, recliquez dessus pour le supprimer, l'événement OnSelect est déclenché dès la pose du second point
Vous pourrez alors créer une ligne ou un polygone avec SelectionTo, ou accèder directement aux points sélectionnés avec Selection[x]
procedure form.doSelect(Sender: TObject);
begin
// convert selected points to a new line
if not assigned(NewLine) then
newLine := map.addLine(0,0);
SelectLine.SelectionTo(newLine);
// convert selected points to a new polygone
if not assigned(NewPoly) then
newPoly := map.addPolygone(0,0);
SelectLine.SelectionTo(newPoly);
end;
end;
Utilisez SelectionFrom(ALat,ALng,BLat,BLng) pour sélection le segment par code.
SelectLine.SelectionFrom(Alat,ALng,BLat,BLng);
// returns the distance (double) of the selection in km
d := SelectionDistance;
// return number of points in selection
SelectLine.Count;
// return point (TECPointLine) number x in selection
P := SelectLine.Selection[x];
// deselect portion by code
SelectLine.Deselect;
Ligne géodésique
Une géodésique est le chemin le plus court entre deux point, utilisez la fonction AddGeodesicLine pour en créer une.
const GroupName: string = '';
const maxSegmentLength:integer=5000): TECShapeLine;
Il vous faut au minimum indiquer les coordonnées de deux points.
maxSegmentLength défini la taille maximale, en mètres, des segments intermédiaires.
PtA,PtB : TECShapeMarker;
...
PtA := map.shapes.Markers[0];
PtB := map.shapes.Markers[1];
line := map.AddGeodesicLine(PtA.Latitude,ptA.Longitude,ptB.Latitude,ptB.Longitude);
Enregistrer son déplacement
Le but de cet exemple est d'enregistrer son déplacement dans une TECShapeLine, un triangle pointant dans la direction du déplacement indiquera la position actuelle.
var
MyLocationShape : TECShapePOI;
MyLocationLine : TECShapeLine;
procedure
TForm1.FormCreate;
begin
// create triangle
MyLocationShape := map.AddPoi(0, 0);
MyLocationShape.POIShape := poiTriangle;
MyLocationShape.Width := 18;
MyLocationShape.height := 24;
MyLocationShape.YAnchor := 0
;
MyLocationShape.visible := false;
end;
// Connect this to your
TLocationSensor.OnLocationChanged
// save your location in a
TECShapeLine
procedure
TForm1.LocationSensorLocationChanged(Sender:
TObject;
const OldLocation,
NewLocation: TLocationCoord2D);
begin
map.beginupdate;
// create new line if not
assigned
if not assigned(MyLocationLine)
then
begin
MyLocationLine := map.AddLine(NewLocation.Latitude,
NewLocation.Longitude,
'mylocations');
MyLocationLine.weight := 4;
MyLocationLine.Color := GetRandomColor;
// add border
MyLocationLine.BorderSize := 2;
MyLocationLine.BorderColor :=
GetShadowColorBy(MyLocationLine.Color, 32);
end
else
MyLocationLine.add(NewLocation.Latitude,
NewLocation.Longitude);
MyLocationShape.SetDirection(NewLocation.Latitude,
NewLocation.Longitude);
MyLocationShape.visible := true;
// center on your
position
map.setCenter(NewLocation.Latitude,
NewLocation.Longitude);
map.endupdate;
end;
Météo
En utilisant les services d'OpenWeatherMap.org vous pouvez afficher la météo le long de votre TECShapeLine.Vous devez tout d'abord obtenir une clef pour utiliser l'api d'OpenWeatherMap
// Get the weather along a TECShapeLine
Line.ShowWeather := true;
Consulter la demo RouteWeather pour plus d'informations sur la façon d'utiliser l'api d'OpenWeatherMap.