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

TECShapeLine

Vous êtes ici :TECNativeMap > Shapes

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

Fig. 1 Une ligne en mode édition

Cette propriétés dispose d'une fonction qui vous permet de trouver la lignes la plus proche d'un point particulier.

var nl : TNearestLine ;
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;
Ajoute un point avec éventuellement son altitude
function Add(const dLatLngs: array of double): integer;
Ajoute un tableau de points, constitué d'une suite de latitudes et de longitudes
line.add([lat1,lng1,lat2,lng2,...,latx,lngx]);

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.

1
procedure Insert(const index: integer; const Lat, Lng : double; const Alt: double = _ErrorAltitude);
Insère un point avec éventuellement son altitude
procedure Reverse
Inverse le sens de la ligne

property ShowDirection : boolean
Ajoute des flêches à chaque segment pour montrer la direction

Fig. 2 ShowDirection

procedure Slice(ALat,ALng,BLat,BLng:double;Line: TECShapeLine);
Copier dans Line la partie délimitée par les coordonnées géographique
Si ces points ne sont pas sur la ligne, ils sont remplacés par les points les plus proches situés sur le ligne
function Slice(ALat,ALng,BLat,BLng:double;GroupName: string = ''): TECShapeLine;
Retourne une ligne composée de la portion délimitée par les coordonnées géographique
Si ces points ne sont pas sur la ligne, ils sont remplacés par les points les plus proches situés sur le ligne
procedure Slice(const StartIndex,EndIndex : integer;Line : TECShapeLine);
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

Fig. 3 slice - red color between 1.2 km and 3.8 kilometer

var redLine:TECShapeLine;

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;
Efface les points

property Encoded: string ;

Encode / Decode le polyline en utilisant l'algorithme de google ( developers.google.com/maps/documentation/utilities/polylinealgorithm )

property EncodePrecision: byte;

Précision d'encodage, par défaut 5 décimales (180.00000 to -180.00000)

procedure Delete(index: integer);

Supprime un segment de la ligne
function Count: integer;
Indique le nombre de segment
property Weight: byte
Épaisseur de la ligne
property BorderSize : integer
Épaisseur de la bordure
property BorderColor : TColor
Couleur de la bordure
property HoverBorderColor : TColor
Couleur de la bordure au survol de la souris

Fig. 4 Bordure noire de 2 pixels

property PenStyle : TPenStyle
type de trait psSolid, psDash, psDot, psDashDot et psUserStyle sont disponibles

En utilisant psUserStyle et setCustomDash([len_dash,len_space,..,len_dashx,len_spacex]) vous pouvez créer votre schéma de traits

line.penStyle := psUserStyle;
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)

Fig. 5 Penstyle := psDashDot - LineType := ltBezier

procedure getAltitudes(Event: TOnGetAltitude = nil);

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;

function getLatLngFromMeter(const SensStartEnd: boolean;
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ètre

dLatitude,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)

property HoverPoint: integer read FHOverSeg;
Index du segment pointé par la souris
property Path[index: integer]: TECPointLine ; default;

Tableau contenant l'ensemble des points de la ligne

TECPointLine = class
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]

1
property PathIndexChange: integer
Indique l'index du point qui a été ajouté,supprimé ou déplacé
property PathChange : TPathChange
Indique la nature du changement : pcDelete, pcAdd ou pcMove
function Distance : double;
Indique la distance totale de la ligne en km
function DistanceBetweenIndexPoint(const idxA,idxB: integer): double;
Retourne la distance en km entre 2 points de la ligne
function DistanceBetween(const ALat,ALng,BLat,BLng:double): double ;

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

function DistanceToPoint(Const ALat,ALng:double): double ;

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.

property Duration : integer;
Si la ligne représente un itinéraire (route) indique la durée du trajet.
property NorthEastLatitude: double
Latitude du coin supérieur droit de la boite englobant la ligne
property NorthEastLongitude: double
Longitude du coin supérieur droit de la boite englobant la ligne
property SouthWestLatitude: double
Latitude du coin inférieur gauche de la boite englobant la ligne
property SouthWestLongitude: double
Longitude Latitude du coin inférieur gauche de la boite englobant la ligne

// Delphi map component TECNativeMap

line := map.Shapes.Lines[0];

// show the entire line
map.fitBounds(line.NorthEastLatitude,line.NorthEastLongitude,line.SouthWestLatitude,line.SouthWestLongitude);

property ShowText : boolean
Si la ligne représente une route permet d'afficher les diverses étapes
property Shapes : TECShapes

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;

Fig. 6 Ajout de drapeaux pour le départ et l'arrivée

Mode édition

property Editable : boolean
Rend éditable la ligne ou le polygone, un click long sur un point le supprime, un double clic sur un segment ajoute un point, l'élément est déplaçable à la souris, faites un clic droit sur le dernier point pour quitter le mode d'édition

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

2

Fig. 7 Lines & Polygones editable

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

1

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.

Fig. 8 Edit line

Utilisez les propriétés FilenameStartEditLine, FilenameEndEditLine, FilenamePointEditLine de votre carte pour changer les bitmaps

// Reverse the point of departure and arrival
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;


Fig. 9 Modification de l'apparence des points d'une TECShapeLine

property OnShapePathChange : TNotifyEvent
Permet d'être informé lorsque le tracé de la ligne change.

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)

var SelectLine : TecNativeLineSelect;
...
SelectLine := TecNativeLineSelect.create;
// triggered by selection
SelectLine.OnSelect := doSelect;
// triggered by deselection
SelectLine.OnDeselect := doDeselect;

SelectLine.Line := your_Line;

Fig. 10 Sélection d'une partie d'une ligne ou d'un polygone

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]

// triggered by selection
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.

// select portion by 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.

function TNativeMapControl.AddGeodesicLine(const SLat,SLng,ELat,ELng:double;
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.

var line:TECshapeLine;
PtA,PtB : TECShapeMarker;
...

PtA := map.shapes.Markers[0];
PtB := map.shapes.Markers[1];
line := map.AddGeodesicLine(PtA.Latitude,ptA.Longitude,ptB.Latitude,ptB.Longitude);

Fig. 11 geodesic line

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.

Fig. 12 Weather on the road

Vous devez tout d'abord obtenir une clef pour utiliser l'api d'OpenWeatherMap

map.OpenWeather.Key := your_key;

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

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