Cette section de la documentation est consacrée aux types de base du langage Ocelet. Ces types peuvent être utilisés lors de la déclaration d'une variable, ou d'une propriété d'entité. Une type est en quelque sorte la nature de la variable ou de la propriété : du texte, une valeur numérique, un polygone par exemple.
Le langage Ocelet reprend un certain nombre de types de base du langage Java : Boolean, Double, Float, Integer, Long, String mais il en contient d'autres qui ont été ajoutés pour les besoins spécifiques de la modélisation de dynamiques spatiales.
A chacun de ces types de base sont associées des fonctions qui permettent d'effectuer des opérations spécifiques à ce type. Par exemple il existe une fonction length() qui permet d'obtenir la longueur du texte contenu dans les variables de type String. Autre exemple, il existe une fonction area() qui permet d'obtenir la surface des variables de type Polygon ou MultiPolygon.
Nous abordons dans un premier temps la méthode générale pour initialiser une variable. Nous distinguons ensuite les trois sortes de types (simples, composites, collections), afin de présenter les différences en matière de création de variables et d'initialisation. Enfin chaque type est détaillé ainsi que les fonctions qui lui sont spécifiques.
Comme on peut le voir dans le chapitre relatif aux instructions de base d'Ocelet, on peut déclarer une constante avec le mot clé fix
et une variable avec le mot clé let
et l'on doit en même temps indiquer une valeur initiale à placer dans la constante ou la variable.
La syntaxe générale pour fournir cette valeur initiale est la suivante :
identifiant
=
new
type(
valeurs initiales)
Voici quelques exemples d'initialisation de constantes et de variables respectant cette syntaxe :
let temperature = new Double(25.0)
fix lis_altitudes = new List<Double>()
let isActive = new Boolean(true)
fix nb_annees = new Integer(12)
fix contour = new Polygon()
Dans la pratique on n'est pas toujours obligé d'utiliser cette syntaxe. Il existe d'autres fonctions et méthodes pour fournir des valeurs initiales, mais elles sont différentes selon qu'il s'agit de type simples, de types composites, ou de collections.
Nous ferons la distinction entre trois sortes de types afin d'expliquer ce qui les différencie dans la façon d'initialiser des variables (ou des propriétés d'entités)
Il s'agit de types de variables qui ne contiennent qu'un seule valeur :
L'initialisation de variables ou constantes avec des types simples peut être allégée, sans faire appel au mot clé new
et même sans préciser le type. Ocelet va tenter de deviner le type d'après le contenu écrit derrière le =
. Ce mécanisme est généralement appelé inférence de type.
Par exemple on pourra écrire :
let temp = 34.7
fix nom = "Bellecombe"
let isActive = true
au lieu de
let temp = new Double(34.7)
fix nom = new String("Bellecombe")
let isActive = new Boolean(true)
Pour que l'inférence de type soit correcte, il faut être rigoureux dans la façon dont on initialise une variable. Par exemple si on écrit let g = 0
, la variable g sera considérée comme un Integer. Pour que cette variable soit de type Double il faudra l'initialiser avec 0.0
. Vous pouvez vous reporter à la documentation détaillée de chacun des types pour connaitre les syntaxes exactes garantissant que le type inféré sera le bon.
Il s'agit de type contenant un nombre fini (et connu à l'avance) de valeurs. Ces valeurs pouvant être soit de type simple, soit d'un type composite, soit une collection. Les types composites de base d'Ocelet sont :
A ces types de base, on peut ajouter les types composites définis par vous même que l'on appelle les Structure. Enfin Les entités, les relations, les datafacers que vous définissez dans un modèle peuvent eux aussi être considérés comme des types composites, au moins parce que les règles de création et d'initialisation de variable à appliquer dans leurs cas sont les mêmes que pour les types composites.
Dans le cas général, on peut toujours créer une variable (ou une constante) sans fournir aucune valeur d'initialisation et ce sont des valeurs par défaut qui seront utilisées. Comme on ne passe aucun argument dans les parenthèses, celles-ci peuvent être retirées.
Par exemple on peut écrire :
let now = new DateTime
let mycolor = new Color
let contour = new Polygon
La valeur par défaut dépend bien sur du type. Ici la variable now
contiendra la date et l'heure du moment ou l'instruction a été exécutée; mycolor
contiendra un gris clair; et contour
sera un polygone vide (ne contenant aucun point).
Certains types composites disposent de fonctions spécifiques d'initialisation
La syntaxe pour utiliser ces fonctions d'initialisation est la suivante :
identifiant
=
type|
fonction d'initialisation(
arguments de la fonction)
On remarquera l'absence du mot clé new
dans ce cas.
Voici quelques exemples respectant cette forme d'initialisation :
let start = DateTime|fromString("dd-MM-YYYY","01-02-2016")
let mycolor = Color|rgba(255,230,230,128)
let position = Point|xy(570680.0,4832818.0)
Il faut se référer à la documentation de chaque type pour connaitre la liste des fonctions d'initialisation disponibles et les arguments à leur passer.
Il faut enfin savoir que l'on peut écrire soi-même des fonctions d'initialisation pour les entités que l'on définit. Se reporter pour cela à la documentation portant sur les entités (voir le mot clé init).
Ce sont des types contenant un certain nombre de valeurs que l'on ne connait pas forcément à l'avance. Ces types de collections sont :
On commence par créer une collection vide, puis on ajoutera des objets dans un second temps. Au moment de la création d'une nouvelle collection, il faut indiquer de quel type sont les objets que l'on va placer dans cette collection.
La syntaxe est de la forme :
identifiant
=
new
type de collection<
type du contenu>
Par exemple on peut préparer une liste de nombres entiers avec :
fix serie = new List<Integer>
puis ajouter des valeurs :
serie.add(5)
serie.add(8)
serie.add(3)
La fonction qui permet d'ajouter des valeurs dépend du type de collection. Ainsi la fonction add() est présente pour List et Group mais pas dans Keymap par exemple.
Dans l'exemple ci-dessus, on remarquera que la liste est créée sous la forme d'une constante (on a utilisé fix
plutot que let
). En effet, la liste elle même, c'est à dire le contenant, n'a pas vocation à changer, cela n'empèchera pas d'ajouter ou de retirer du contenu. Cela dit, il serait possible de placer cette liste dans une variable (avec let
) si l'on désire par la suite remplacer cette liste par une autre dans cette variable. Dans ce dernier cas cela signifie que c'est un contenant (la première liste) qui sera remplacé par un autre contenant (une seconde liste).
Enfin à l'image de certains types composites, les types de collection List et Group possèdent une fonction d'initialisation of() qui permet de créer une collection et de la remplir avec du contenu en une seule instruction. Le type du contenu est déduit de ce que l'on ajoute, et bien entendu tous les objets ajoutés doivent être de même type.
Exemples :
fix series = List|of(5,8,3)
fix semaine = List|of("lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche")
Nombre décimal en double précision (encodé sur 64bits). Il s'agit du type utilisé par défaut dans Ocelet lorsque l'on déclare une variable initialisée avec un nombre décimal. Mais on peut aussi forcer la valeur numérique à être de type Double en ajoutant la lettre D à la fin :
let t = 0.12
let u = 2D
let v = 0.1546D
let h = 1.234e4
t, u,v et h seront toutes de type Double. Dans cet exemple la valeur 1.234e4 est exprimée en notation scientifique, elle équivalente à 1.234 x 10000 = 12340.0
Dans la définition d'une propriété d'entité ou de relation, on n'initialise pas directement la propriété, et il est donc nécessaire d'indiquer le type voulu :
entity Station {
property Double temp
}
Nombre décimal en simple précision (encodé sur 32bits). Si l'on veut initialiser une variable avec une valeur décimale en type Float is est nécessaire d'ajouter la lettre F à la fin :
let u = 2F
let h = 1.234e4
let v = 0.1546F
u,v et h seront toutes trois de type Float. Dans cet exemple la valeur 1.234e4 est exprimée en notation scientifique, elle équivalente à 1.234 x 10000 = 12340.0
Dans la définition d'une propriété d'entité ou de relation, on n'initialise pas directement la propriété, et il est donc nécessaire d'indiquer le type voulu :
entity Station {
property Float temp
}
Nombre entier (encodé sur 32bits). Il s'agit du type utilisé par défaut dans Ocelet lorsque l'on déclare une variable initialisée avec un nombre entier :
let u = 2
let h = 4e5
_u et h seront de type Integer. Dans cet exemple la valeur 4e5 est exprimée en notation scientifique, elle équivalente à 4 x 100000 = 400000
Dans la définition d'une propriété d'entité ou de relation, on n'initialise pas directement la propriété, et il est donc nécessaire d'indiquer le type voulu :
entity Station {
property Integer temp
}
Nombre entier long (encodé sur 64bits). Ce n'est pas le type utilisé par défaut dans Ocelet lorsque l'on déclare une variable initialisée avec un nombre entier. Pour initialiser une variable avec un entier long il faut impérativement ajouter la lettre L à la fin du nombre:
let u = 2L
u sera de type Long.
Dans la définition d'une propriété d'entité ou de relation, on n'initialise pas directement la propriété, et il est donc nécessaire d'indiquer le type voulu :
entity Station {
property Long temp
}
Il arrive que la manipulation de variables de types numériques différents entraine des conflits de typage qui doivent être résolus. On fait alors appel à des fonctions de conversion de type.
Un tel conflit peut survenir si l'on essaye d'arondir un nombre qui est de type Double pour l'affecter à une variable qui est de type Integer :
let t=112.5 // t est de type : Double
let f=0 // f est de type Integer
f=round(t) // Conflit de type
La fonction round() produit effectivement un nombre entier, mais comme t est de type Double, round(t) va produire un nombre de type Long. Et le conflit vient ici du fait que l'on ne peut pas affecter un Long à une variable de type Integer parce qu'il y a un risque de perdre de l'information si ce nombre est très grand. C'est donc à vous de forcer la conversion de type si vous estimez que ce risque n'existe pas dans le contexte de votre programme. Dans le cas présent on utilisera la fonction de conversion intValue() :
let t=112.5 // t est de type : Double
let f=0 // f est de type Integer
f=round(t).intValue() // Pas de conflit de type, on obtient bien un Integer
Les fonctions de conversion de type numérique sont :
Double doubleValue()
Float floatValue()
Integer intValue()
Long longValue()
Ces fonctions permettent la création d'une valeur d'un type numérique donné, autrement qu'en fournissant directement sa valeur. Elles sont disponibles pour tous les types numériques :
valueOf( Double nombre )
valueOf( String texte )
Exemple :
let t = 25 // t est de type Integer
let u = Double|valueOf(t) // u sera un Double
let v = Double|valueOf("240") // Crée un Double à partir du texte "240"
Type qui représente un état binaire : soit vrai soit faux.
let v=true
Une variable de type Boolean peut être utilisée dans un test :
if (v) println("Ok.") else println("Not ok.")
Type utilisé pour contenir une couleur. Les variables de type Color sont particulièrement utiles pour donner des indications de style lorsque l'on produit des cartes en résultat de simulation.
Color est un type composite, c'est à dire constitué de plusieurs composantes. La déclaration d'une variable de type Color sans autre précision fournir une couleur par défaut (gris clair) :
let defautColor = new Color
Pour choisir les composantes on passe donc par une fonction d'initialisation.
rgb(Integer rouge, Integer vert, Integer bleu)
: rouge, vert, bleu sont des entiers compris entre 0 et 255. Ils représentent les composantes de la couleur que l'on souhaite obtenir.rgba(Integer rouge, Integer vert, Integer bleu, Integer alpha)
: alpha est aussi un entier compris entre 0 et 255 et représente un niveau d'opacité (souvent nommé alpha channel). La valeur 0 est totalement transparente, la valeur 255 est totalement opaque.text(String rvb)
: cette fonction d'initialisation a été ajoutée pour pouvoir obtenir une couleur directement à partir d'une représentation textuelle de ses composantes, telle qu'on peut la trouver dans certains formats de fichiers comme CSS (Cascading Style Sheet) par exemple. Ces deux formes d'expression sont valides :
Exemples :
let color1 = Color|rgb(255,255,168) // produit un jaune pale totalement opaque
let color2 = Color|rgba(255,128,255,128) // produit un rose avec 50% de transparence
let color3 = Color|text("#FF80FF80") // produit un rose avec 50% de transparence
Une fois que l'on dispose d'une variable de type Color, on peut lui appliquer les fonctions suivantes :
Color darker( Double proportion )
: Produit une nouvelle couleur, plus foncée que la couleur d'origine, selon la proportion fournie. proportion est une valeur de type Double comprise entre 0 et 1.Color lighter( Double proportion )
: Produit une nouvelle couleur, plus claire que la couleur d'origine, selon la proportion fournie. proportion est une valeur de type Double comprise entre 0 et 1.List<Color> colorRange( Integer nombre_de_couleurs , Color couleur )
: Produit un dégradé de couleurs sous la forme d'une liste (de type List< Color >). Le nombre de couleurs intermédiaire contenu dans cette liste est indiqué par un nombre entier. La fonction va donc produire un dégradé de couleurs entre la couleur à laquelle on applique la fonction et l'autre couleur fournie.String toString()
: Produit une représentation textuelle de la couleur, sous la forme "rgb(r,v,b)"Exemples :
let color1 = Color|rgb(255,255,168) // jaune pale
let color4 = color1.darker(0.5) // beige : rgb(127,127,84)
let degrad = color1.colorRange(8,Color|rgb(0,128,255)) // Dégradé de jaune vers bleu en 8 couleurs
Type permettant la manipulation de dates et d'heures. Ce type est pratique pour intégrer des champs d'information temporelle dans les données issues de simulation.
Attention : le type DateTime n'existe dans Ocelet que depuis la version 2.0. Il remplace le type Date qui était utilisé jusque là. Le type Date est considéré comme obsolete et l'éditeur d'Ocelet barre le type Date quand on essaye de l'utiliser pour indiquer qu'il est préférable d'utiliser le nouveau type DateTime. La principale différence entre les types Date et DateTime est que les fonctions pour changer la date ou l'heure affectaient directement le contenu des variables de type Date mais elle n'affectent pas le contenu des variables de type DateTime. Avec le type DateTime, il n'est donc plus nécessaire de faire un clonage de date pour en obtenir une copie. Mais il faut desormais récupérer le résultat des fonctions modifiant la date ou l'heure (voir les exemples indiqués plus loin).
Il est possible de créer un exemplaire de DateTime sans initialiser le contenu, la variable contiendra alors la date et l'heure de l'ordinateur au moment de l'exécution de cette instruction :
let now = new DateTime
DateTime est un type composite, c'est à dire constitué de plusieurs composantes : année, mois, jour, heure, minutes, secondes et millisecondes. L'initialisation d'une variable de type DateTime peut se faire à l'aide d'une fonction d'initialisation.
ymd(Integer année, Integer mois, Integer jour)
: Produit une DateTime à partir de trois nombres entiers fournis, représentant l'année, le mois et le jour. Dans ce cas, l'heure sera à 00:00:00.fromString(String format , String date )
Produit une DateTime à partir d'un texte dont le format est décrit par un motif. Le motif est constitué de caractères qui désignent un élément de date ou d'heure, voir le tableau des motifs de formatage.Exemples :
let date1 = DateTime|ymd(2010, 12, 25) // DateTime produit: 25 dec. 2010 00:00:00
let date2 = DateTime|fromString("yyyy-MM-dd kk:mm","2010-12-25 15:30") // DateTime produit: 25 dec. 2010 15:30:00
Les fonctions disponibles sur le type DateTime sont nombreuses. Nous les avons classées par groupes de fonctions similaires.
Comme cela est indiqué par le type de retour de ces fonctions, elles renvoient toutes un nouvel exemplaire de DateTime. La variable sur laquelle on applique l'une de ces fonctions n'est pas modifiée. Autrement dit, si l'on veut obtenir ou nouvelle date ou heure dans la même variable, il faut lui affecter le résultat renvoyé.
DateTime addYears(Integer nb_annees)
: Ajoute le nombre d'années indiqué à la date.DateTime addMonths(Integer nb_mois)
: Ajoute le nombre de mois indiqué à la date.DateTime addWeeks(Integer nb_semaines)
: Ajoute le nombre de semaines indiqué à la date.DateTime addDays(Integer nb_jours)
: Ajoute le nombre de jours indiqué à la date.DateTime addHours(Integer nb_heures)
: Ajoute le nombre d'heures indiqué à la date.DateTime addMinutes(Integer nb_minutes)
: Ajoute le nombre de minutes indiqué à la date.DateTime addSeconds(Integer nb_secondes)
: Ajoute le nombre de secondes indiqué à la date.Exemple :
let date3 = DateTime|fromString("yyyy-MM-dd","2010-01-20")
date3 = date3.addWeeks(2) // Ajout de 2 semaines => 3 fev. 2010
Ces fonctions renvoient toutes un nombre entier qui correspond à un des éléments de la date ou de l'heure. Le nom de chaque fonction indique l'élément renvoyé.
Integer getYear()
: Renvoie l'annéeInteger getMonth()
: Renvoie le moisInteger getDayOfWeek()
: Renvoie le jour de la semaineInteger getDayOfMonth()
: Renvoie le jour du moisInteger getDayOfYear()
: Renvoie le jour de l'année.Integer getHour()
: Renvoie l'heureInteger getMinute()
: Renvoie les minutesInteger getSecond()
:Renvoie les secondesInteger getMillisecond()
: Renvoie les millisecondesLong getTimeAsMilliseconds()
: Renvoie un entier long qui correspond au nombre de millisecondes écoulées depuis minuit pour cette date. Autrement dit l'heure courante de cette date est convertie en millisecondes.Ces fonctions prennent toutes un nombre entier comme paramètre et renvoient un nouvel exemplaire de DateTime. La variable sur laquelle la fonction est appellée n'est pas modifiée. Le nom de chaque fonction indique l'élément modifié.
DateTime withYear(Integer annee)
: Change l'annéeDateTime withMonth(Integer mois)
: Change le moisDateTime withDayOfWeek(Integer jour)
: Change le jour dans la semaineDateTime withDayOfMonth(Integer jour)
: Change le jour dans le moisDateTime withDayOfYear(Integer jour)
: Change le jour dans l'annéeDateTime withHour(Integer heures)
: Change l'heureDateTime withMinute(Intger minutes)
: Change les minutesDateTime withSecond(Integer secondes)
: Change les secondesDateTime withMillisecond(Integer millisecondes)
: Change les millisecondesExemple :
let date3 = DateTime|fromString("yyyy-MM-dd","2010-01-20")
date4 = date3.withMonth(5) // Change le mois: date4 = 20 mai 2010
// Dans cet exemple on a récupéré le résultat dans date4
// la date et l'heure de la variable date3 n'ont pas changé.
Boolean isAfter(DateTime date)
: Renvoie une valeur de type Boolean. Renvoie true
(vrai) si la date (et l'heure) fournie est postérieure à la date sur laquelle on appelle cette fonction.Boolean isBefore(DateTime date)
: Renvoie une valeur de type Boolean. Renvoie true
(vrai) si la date fournie est antérieure à la date sur laquelle on appelle cette fonction.Exemple :
let date1 = DateTime|fromString("yyyy-MM-dd","2010-01-20")
let date2 = DateTime|fromString("yyyy-MM-dd","2010-02-22")
date1.isAfter(date2) // => false
date1.isBefore(date2) // => true
L'écart entre deux DateTime peut être obtenu dans une unité temporelle de votre choix (années, mois, jours, heures, minutes, secondes, millisecondes). Les fonctions usuelles pour obtenir cela sont :
yearsDifference(DateTime d)
monthsDifference(DateTime d)
daysDifference(DateTime d)
hoursDifference(DateTime d)
minutesDifference(DateTime d)
secondsDifference(DateTime d)
millisecondsDifference(DateTime d)
Si le DateTime d
que l'on passe en argument est postérieur au DateTime sur lequel on applique une fonction, le resultat sera positif, sinon il sera négatif.
Exemple :
fix date1 = DateTime|ymd(2010, 12, 25)
fix date2 = DateTime|fromString("yyyy-MM-dd kk:mm","2010-12-27 15:30")
println("Number of months between date1 and date 2: "+date1.monthsDifference(date2))
println("Number of days between date1 and date 2: "+date1.daysDifference(date2))
println("Number of hours between date1 and date 2: "+date1.hoursDifference(date2))
println("Number of minutes between date1 and date 2: "+date1.minutesDifference(date2))
produira :
Number of months between date1 and date 2: 0
Number of days between date1 and date 2: 2
Number of hours between date1 and date 2: 63
Number of minutes between date1 and date 2: 3810
String toString()
: Produit une représentation textuelle de la date et de l'heure en utilisant le formatage par défaut.String toString( String format )
: Produit une représentation textuelle de la date et de l'heure en utilisant le formatage spécifié par le motif fourni. Le motif est construit à l'aide de caractères qui désignent un élément de date ou d'heure, voir le tableau des motifs de formatage.Exemple :
let date1 = DateTime|fromString("dd/MM/yy","22/02/10")
println("Date : "+date1.toString("yyyy-MM-dd")) // Texte affiché => Date : 2010-02-22
Lorsque l'on utilise un formatage sur une variable de type DateTime, ce formattage est conservé. Autrement dit ce formattage devient le formattage d'affichage par défaut de la date et l'heure pour cette variable, il n'est plus nécessaire de l'indiquer.
Caractère | Element d'heure ou de date | Exemples |
---|---|---|
G
|
Epoque chrétienne |
ap. J.-C.
|
y
|
Année |
1996 ; 96
|
Y
|
Année |
2009 ; 09
|
M
|
Mois de l'année |
Juillet ; Jul ; 07
|
w
|
Semaine dans l'année |
27
|
W
|
Semaine dans le mois |
3
|
D
|
Jour dans l'année |
239
|
d
|
Jour dans le mois |
10
|
F
|
Jour de la semaine dans le mois |
2 (2eme mercredi du mois)
|
E
|
Nom du jour de la semaine |
Vendredi ; Ven
|
u
|
Numéro du jour de la semaine (1 = Lundi, :.., 7 = Dimanche) |
1
|
a
|
Marqueur matin ou après-midi |
PM
|
H
|
Heure du jour (0-23) |
0
|
k
|
Heure du jour (1-24) |
24
|
K
|
Heure dans la demi-journée (0-11) |
0
|
h
|
Heure dans la demi-journée (1-12) |
12
|
m
|
Minutes dans l'heure |
30
|
s
|
Second dans la minute |
55
|
S
|
Millisecondes |
978
|
z
|
Fuseau horaire |
Pacific Standard Time ; PST ; GMT-08:00
|
Z
|
Fuseau horaire |
-0800
|
X
|
Fuseau horaire |
-08 ; -0800 ; -08:00
|
Ce type représente une série de caractères qui constitue un texte. Il est possible d'initialiser une variable de type String directement avec un texte, ce texte doit être encadré par le caractère "
.
Exemple :
let nom = "Curepipe"
Integer compareTo( String texte )
: compare notre texte avec celui fourni en paramètre. Cette comparaison distingue les majuscules de minuscules.
Integer compareToIgnoreCase( String texte )
: compare notre texte avec celui fourni en paramètre. Cette comparaison ne fait pas de différence entre majuscules et minuscules.
String concat( String texte )
: Ajoute le texte fourni au bout du notre.Boolean endsWith( String texte )
: Renvoie true (vrai) si le texte fourni termine le notre.Boolean equals( String texte )
: Renvoie true (vrai) si le texte fourni est identique au notre. Cette comparaison fait la distinction entre les majuscules et les minuscules.Boolean equalsIgnoreCase( String texte )
: Renvoie true (vrai) si le texte fourni est identique au notre. Cette comparaison ne fait pas de différence entre majuscules et minuscules.Integer indexOf( String texte )
: Renvoie la position du texte fourni dans le notre, ou -1 si celui-ci ne s'y trouve pas.Integer indexOf( String texte , Integer index )
: Renvoie la position du texte fourni dans le notre en commençant la recherche à partir de l'index, ou -1 si celui-ci ne s'y trouve pas.Integer lastIndexOf( String texte )
: Renvoie la position de la dernière occurence du texte fourni à l'intérieur du notre.Integer lastIndexOf( String texte , Integer index )
: Renvoie la position de la dernière occurence du texte fourni à l'intérieur du notre, en commençant la recherche à partir de l'index donné.Integer length()
: Donne le nombre de caractères dans le texte.Boolean startsWith(String prefix)
: Renvoie true (vrai) si notre texte commence par le texte fourni.Boolean startsWith(String prefix, Integer index)
: Renvoie true (vrai) si le texte fourni est situé à index donné à l'intérieur de notre texte.String substring(Integer index)
: Retourne la fin du texte en partant de l'index fourni.String substring(Integer debut, Integer fin)
: Retourne la partie du texte située entre les index debut et fin.String toLowerCase()
: Passe le texte en minuscules.String toUpperCase()
: Passe le texte en majuscules.String trim()
: Elimine les blancs au début et à la fin du texte (s'il y en a).Les types de géométrie permettent de manipuler les composantes spatiales de l'information géographique. On y trouve des types de nature ponctuelles, linéaires et surfaciques avec dans chaque cas un type simple et un type multiple. Chaque type de géométrie possède des fonctions d'initialisation qui lui sont propres. Les fonctions d'usage sont les mêmes pour tous (à une exception près) et sont présentées ensemble à la suite des types.
Géométrie simple de type linéaire.
points(Point p1, ...)
: Construit un élément de type Line à partir d'un nombre variable de points fournis en paramètre.points(List<Point> points)
: Construit un élément de type Line à partir d'une liste de Points fournie en paramètre.Exemples :
let segment = Line( Point|xy(100d,50d) , Point|xy(320.4, 55d) )
let lp = new List<Point>
lp.add(Point|xy(100.0,100.0))
lp.add(Point|xy(200.0,100.0))
lp.add(Point|xy(100.0,200.0))
let line2 = Line|points(lp)
List<Point> asListOfPoints()
: Donne accès à une liste de Points correspondant aux coordonnées qui constituent cet objet linéaire.Geométrie linéaire multiple. Ce type regroupe plusieurs éléments linéaires dans une même variable.
lines(Line l1, ...)
: Construit un élément de type MultiLine à partir d'un nombre variable de Lines fournis en paramètre.lines(List<Line> lines)
: Construit un élément de type MultiLine à partir d'une liste de Lines fournie en paramètre.List<Line> asListOfLines()
: Donne accès à une liste de Line représentant le contenu de ce MultiLine.Géométrie simple ponctuelle.
xy(Double x, Double y)
: Contruit un Point à partir des coordonnées fournies en argument.xyz(Double x, Double y, Double z)
: Contruit un Point à partir des coordonnées fournies en argument, z représente une altitude.Géométrie ponctuelle multiple. Ce type regroupe un ensemble d'éléments ponctuels dans une même variable.
points(Point p1, ...)
: Construit un élément de type MultiPoint à partir d'un nombre variable de Points fournis en paramètre.points(List<Point> points)
: Construit un élément de type MultiPoint à partir d'une liste de Points fournie en paramètre.List<Point> asListOfPoints()
: Donne accès à une liste de Points qui constituent ce MultiPoint.Géométrie surfacique simple.
points(Point p1, ...)
: Construit un élément de type Polygon à partir d'un nombre variable de points fournis en paramètre.points(List<Point> points)
: Construit un élément de type Polygon à partir d'une liste de Points fournie en paramètre.List<Point> asListOfPoints()
: Donne accès à une liste de Points qui constituent le contour extérieur de ce Polygon.Geométrie surfacique multiple. Ce type regroupe plusieurs éléments surfaciques dans une même variable.
polygons(Polygon l1, ...)
: Construit un élément de type MultiPolygon à partir d'un nombre variable de Polygons fournis en paramètre.polygons(List<Polygon> polys)
: Construit un élément de type MultiPolygon à partir d'une liste de Polygons fournie en paramètre.List<Polygon> asListOfPolygons()
: Donne accès à une liste des Polygon contenus dans ce MultiPolygon.Ces fonctions peuvent être appliquées aux variables de tous les types de géométries. Pour simplifier la description de ces fonctions, nous utilisons Geom
pour désigner un type de géométrie de manière générique (ce type Geom
ne peut être utilisé dans un programme Ocelet).
Geom buffer(Double largeur)
: Produit une zone tampon autour de notre objet dont la largeur est fournie en paramètre.Boolean contains(Geom objet)
: Teste si notre objet contient entièrement l'objet fourni en paramètre et renvoie true
(vrai) si c'est le cas.Boolean disjoint(Geom objet)
: Teste si l'objet fourni et le notre sont disjoints et renvoie true
(vrai) si c'est le cas.Double distance(Geom objet)
: Renvoie la distance entre notre objet et celui qui est passé en paramètre.Double getArea()
: Renvoie la surface de notre objet. Bien entendu il n'y a que pour des objets de type surfacique que l'on obtient une valeur supérieure à 0.Line getBoundary()
: Retourne le linéaire qui constitue la frontière extérieure de notre objet.Point getCentroid()
: Produit un Point situé au barycentre de notre objet. Attention, le centroide d'un polygone ne se trouve pas forcément à l'intérieur de ce polygone.Integer getDimension()
: Renvoie la dimension spatiale de la géométrie de notre objet :
Point getEndPoint()
: Renvoie le dernier Point de notre objet.Geom getEnvelope()
: Renvoie le rectangle englobant notre objet.Point getInteriorPoint()
: Produit un Point situé à l'intérieur de notre objet. Le temps nécessaire pour calculer la position de ce point est plus bien plus important que pour la fonction getCentroid().Integer getNumPoints()
: Retourne le nombre de points dont notre objet est constitué.Point getpointN(Integer index)
: Renvoie le Point situé à la position fournie dans index, selon l'ordre des points dont notre objet est constitué.Point getStartPoint()
: Renvoie le premier Point de notre objet.Boolean intersects(Geom objet)
: Teste si l'objet fourni est en intersection avec le notre et renvoie true
(vrai) si c'est le cas.Boolean isValid()
: Teste si la géométrie de notre objet est valide et renvoie true
(vrai) si c'est le cas. Ce test n'est pertinent que sur les objets surfaciques. Ils sont valides si :
Geom intersection(Geom objet)
: Renvoie un nouvel objet dont la géométrie est le résultat de l'intersection entre notre objet et l'objet fourni.Geom move(Double dx, Double dy)
: Déplace cet objet selon les distances dx et dy passées en arguments. L'objet déplacé à la nouvelle position est renvoyé par la fonction.Geom rotate(Double angle, Double anchorx, Double anchory)
: Opère une rotation de cet objet autour d'un point d'ancrage aux coordonnées anchorx,anchory et selon l'angle angle passés en arguments. L'objet résultant de cette rotation est renvoyé par la fonction.Geom scale(Double xfactor, Double yfactor)
: Opère une homothétie sur cet objet selon les facteurs xfactor et yfactor passés en argument. L'objet résultant de cette transformation homothétique est renvoyé par la fonction.Geom union(Geom objet)
: Renvoie un nouvel objet dont la géométrie est le résultat de l'union entre notre objet et l'objet fourni.Il arrive que l'on ait besoin de stocker dans une même variable plusieurs valeurs, éventuellement de natures différentes, que l'on souhaite conserver ensembles. On a besoin de définir son propre type composite. C'est ce que les structures permettent de faire.
Une structure doit être définie dans un modèle, au même niveau qu'une entité, une relation ou un scénario.
structure
Nom{
définitions des variables composant la structure
}
On peut mettre autant de variables qu'on le souhaite. Chaque variable est définie par :
Type identifiant
Le Type est soit un des types de base d'Ocelet ( Integer, Double, Point, etc. ), soit un type composite défini par vous même sous la forme d'une structure.
Le Nom de la structure et les identifiants des variables qu'elle contient doivent impérativement commencer par une lettre mais peut éventuellement être suivi par des chiffres, et ne pas contenir d'espace ni de caractère spéciaux. Le Nom de la structure doit commencer par une lettre majuscule.
Les définitions de structures se trouvent en dehors de tout scenario. A l'intérieur d'un scenario on fait référence à ces définitions pour créer une ou plusieurs variables qui ont une structure pour type.
On peut ensuite accéder directement aux variables internes d'une structure en séparant le nom de la variable et la variable interne par un .
.
structure Deplacement {
Double direction
Double vitesse
}
scenario MonModele {
let dep = new Deplacement
dep.direction = 0.0
dep.vitesse=2.4
dep.direction = 0.3 // change de direction
println("Direction du déplacement :" + dep.direction)
println("Vitesse du déplacement :" + dep.vitesse)
}
Il est possible d'initialiser toutes ou partie des variables internes à une structure au moment de sa création à l'aide de la syntaxe :
indentifiant
=
new
nom de la structure=>
[
affectation des variables]
Le scénario de l'exemple ci-dessus pourrait ainsi être plus court :
scenario MonModele {
let dep = new Deplacement => [direction=0.0 vitesse=2.4]
dep.direction = 0.3 // change de direction
println("Direction du déplacement :" + dep.direction)
println("Vitesse du déplacement :" + dep.vitesse)
}
Les collections sont des types offrant la possibilité de stocker ensemble des séries d'éléments qui sont tous de même type. Ces types de collections sont au nombre de six dans Ocelet : Group, List, KeyMap, KeyMap2d, KeyMap3d, OrdKeyMap.
KeyMap
mais avec conservation de l'ordre des clés.Les collections possèdent toutes des fonctions d'initialisation et des fonctions d'usages qui sont détaillées de manière spécifiques pour chacun des types ci-dessous. Dans cette section de la documentation nous avons noté T
le type des éléments stockés dans le groupe, et à l'usage on peut remplacer ce T
par n'importe quel type d'Ocelet.
Le type Group correspond à la notion d'ensemble non ordonné, avec unicité des éléments qu'il contient. Tous les éléments présents dans un Group doivent être de même type, celui-ci doit être indiqué au moment où l'on déclare une variable qui va contenir le groupe. Par exemple si l'on veut un groupe de Point on déclarera la variable par :
fix gpts = new Group<Point>
Nous avons noté T
pour représenter le type des éléments stockés dans le groupe.
of(T objet1, T objet2, ...)
: Ajoute chacun des objets listés dans le groupe. Tous les objets doivent être du même type que celui qui a été déclaré pour ce Group.Exemple :
fix gint = Group|of(13,67,34,89,1,0,5,6)
fix gpts = Group|of(Point|xy(12.0,45.3),Point|xy(13.5,43.46))
add(T objet)
: Ajoute un objet au groupeaddAll(List<T> elements)
; addAll(Group<T> elements)
: Ces fonctions permettent d'ajouter une série d'éléments provenant respectivement d'une liste ou d'un groupe qui est fourni en paramètre.clear()
: efface tout le contenu.Boolean contains(T objet)
: Renvoie true
(vrai) si le groupe contient l'objet fourni en paramètre.Boolean isEmpty()
: Renvoie true
(vrai) si le groupe est un ensemble vide.remove(T objet)
: Retire l'objet fourni du groupe (si il s'y trouve).Integer size()
: Renvoie le nombre d'éléments contenus dans ce groupe.Bien qu'il ne s'agisse pas directement d'une fonction d'usage, il faut savoir que l'instruction for(..)
peut être utilisée pour parcourir tous les éléments d'un Group. :
// i va prendre successivement la valeur de tous les éléments du group gint
for (i:gint) { println("Entier suivant :"+i) }
Le type List correspond à une série ordonnée d'éléments, dans laquelle on peut éventuellement placer plusieurs fois le même élément. Tous les éléments présents dans une List doivent être de même type, celui-ci doit être indiqué au moment où l'on déclare une variable qui va contenir la liste. Par exemple si l'on veut une liste de Point on déclarera la variable par :
fix lpts = new List<Point>
Dans cette section de la documentation nous avons noté T
le type des éléments stockés dans la liste, et à l'usage on peut remplacer ce T par n'importe quel type d'Ocelet.
of(T objet1, T objet2, ...)
: Ajoute à la liste chacun des objets donnés en argument. Tous les objets doivent être du même type que celui qui a été déclaré pour ce List.Exemple :
let jours = List|of("lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche")
add(T objet)
: Ajoute l'objet fourni à la fin de la liste.add(Integer position, T objet)
: Ajoute l'objet fourni à la position indiquée dans la liste.addAll(List<T> elements)
; addAll(Group<T> elements)
: Ces fonctions permettent d'ajouter une série d'éléments provenant respectivement d'une liste ou d'un groupe qui est fourni en paramètre.addFill(Integer quantite, T valeur)
: Ajoute la valeur à la liste autant de fois que la quantité indiquée.addU(T objet)
: Ajout conservant l'unicité du contenu. L'objet est ajouté seulement si il ne se trouve pas déjà dans la liste.clear()
: efface tout le contenu.Boolean contains(T objet)
: Renvoie true
(vrai) si la liste contient l'objet fourni en paramètre.Integer frequency(T objet)
: Retourne le nombre d'occurences de l'objet fourni.T get(Integer position)
: Retourne l'élément qui se trouve à la position fournie en paramètre. Le premier élément se trouve à la position 0.Boolean isEmpty()
: Renvoie true
(vrai) si la liste est vide.Integer lastIndexOf(T objet)
: Renvoie la position de la dernière occurence de l'objet fourni.remove(T objet)
: Retire la première occurence de l'objet fourni de la liste (si il s'y trouve).reverse()
: Inverse l'ordre des éléments de la liste.rotate(Integer distance)
: Décale les éléments de la liste de la distance indiquée. Tous les éléments sortant d'un côté sont replacés de l'autre côté. Après l'appel à cette fonction, les élements à l'index i seront les éléments qui étaient précédemment à l'index (i-distance) modulo list.size pour toutes les valeurs de i comprises entre 0 et list.size-1 inclus. Cette fonction ne modifie pas la taille de la liste.set(Integer position, T objet)
: Remplace l'élément se trouvant à la position indiquée par l'objet fourni.shuffle()
: Réorganise aléatoirement l'ordre des éléments de la liste.Integer size()
: Renvoie le nombre d'éléments contenus dans cette liste.swap(Integer i, Integer j)
: Echange les éléments se trouvant aux position i et j indiquées.Bien qu'il ne s'agisse pas directement d'une fonction d'usage, il faut savoir que l'instruction for(..)
peut être utilisée pour parcourir tous les éléments d'une List. :
// j va prendre successivement la valeur de tous les éléments de la liste jours
for (j:jours) { println("Jour suivant :"+j) }
Le type est un ensemble associatif qui permet de stocker des couples associant une clé à une valeur. Il n'y a pas de fonction d'initialisation pour KeyMap. On commence par créer une variable de type KeyMap vide, et on y ajoute des couples clé/valeur avec la fonction put(). Au moment de la création d'une variable de type KeyMap il faut indiquer le type des clés et le type des valeurs :
let km = new KeyMap<Integer,String>
km.put(1,"janvier")
km.put(7,"juillet")
Il n'y a pas de fonction d'initialisation pour KeyMap.
Dans cette liste de fonctions, nous avons noté K
pour représenter le type des clés, et V
pour le type des valeurs.
clear()
: efface tout le contenu (clé et valeurs).Boolean containsKey(clé)
: Renvoie vrai
si la clé fournie en argument est présente dans la KeyMap et faux
dans le cas contraire.V get(K clé)
: Renvoie la valeur correspondant à la clé fournie, ou null si cette clé ne se trouve pas dans la KeyMap.put(K clé, V valeur)
: Ajoute un couple clé/valeurremove(K clé)
: Retire le couple clé/valeur correspondant à la clé fournie.Integer size()
: Renvoie le nombre de couples clé / valeur présents dans la variable de type KeyMap.Il est possible de parcourir l'ensemble des clés presentes dans une variable de type KeyMap à l'aide de l'instruction for(...)
et de la fonction keySet()
de la manière suivante (en reprenant la variable km en exemple ci-dessus):
for(key:km.keySet()) {
println("Clé suivante : "+key)
}
Résultat :
Clé suivante : 1
Clé suivante : 7
L'ordre dans lequel on obtient les différentes clés lors de ce parcours est imprévisible. Pour avoir un ordre prévisible il faut utiliser le type OrdKeyMap
à la place de KeyMap
.
On peut aussi parcourir l'ensemble des valeurs de façon similaire à l'aide de la fonction values()
:
for(val:km.values()) {
println("Valeur suivante : "+val)
}
Résultat :
Valeur suivante : janvier
Valeur suivante : juillet
Ensemble associatif qui permet de stocker des données associant deux clés à une valeur. Ce la peut être pratique pour construire l'équivalent d'une matrice peu dense par exemple. Il n'y a pas de fonction d'initialisation pour KeyMap2d. On commence par créer une variable de type KeyMap2d vide, et on y ajoute des clés/valeur avec la fonction put(). Au moment de la création d'une variable de type KeyMap2d il faut indiquer le type des clés et le type des valeurs :
let km2 = new KeyMap2d<Integer,Integer,String>
km2.put(12,30,"fourrage")
km2.put(15,25,"canne")
Il n'y a pas de fonction d'initialisation pour KeyMap2d.
Dans cette liste de fonctions, nous avons noté K
et L
pour représenter le type des clés, et V
pour le type des valeurs.
clear()
: efface tout le contenu (clés et valeurs).Boolean containsKeys(K clé1, L clé2)
: Renvoie vrai
si la combinaison de clés fournies en argument est présentes dans la KeyMap2d et faux
dans le cas contraire.V get(K clé1, L clé2)
: Renvoie la valeur correspondant à la combinaison de clés fournie, ou null si cette combinaison de clés ne se trouve pas dans la KeyMap2d.put(K clé1, L clé2, V valeur)
: Ajoute une valeur associée au couple de clés cle1,clé2
.Le type KeyMap2d<K,L,V>
est en réalité une simplification d'écriture de KeyMap<K,KeyMap<L,V>>
. Cela signifie qu'il est possible d'utiliser les fonctions d'usage du type KeyMap
sur une variable de type KeyMap2d
en sachant que les clés sont de type K
et les valeurs correspondantes de type KeyMap<L,V>.
Par exemple km2.get(12,30)
donnera "fourrage"
, km2.get(12)
donnera une KeyMap<Integer,String>
et donc km2.get(12).get(30)
donnera "fourrage"
.
Ensemble associatif qui permet de stocker des données associant trois clés à une valeur. Il n'y a pas de fonction d'initialisation pour KeyMap3d. On commence par créer une variable de type KeyMap3d vide, et on y ajoute des clés/valeur avec la fonction put(). Au moment de la création d'une variable de type KeyMap3d il faut indiquer le type des clés et le type des valeurs :
let km3 = new KeyMap3d<Integer,Integer,Integer,String>
km3.put(12,30,2020,"fourrage")
km3.put(12,30,2021,"canne")
km3.put(15,25,2020,"canne")
km3.put(15,25,2021,"banane")
Il n'y a pas de fonction d'initialisation pour KeyMap3d.
Dans cette liste de fonctions, nous avons noté K
,L
et M
pour représenter le type des clés, et V
pour le type des valeurs.
clear()
: efface tout le contenu (clés et valeurs).Boolean containsKeys(K clé1, L clé2, M cle3)
: Renvoie vrai
si la combinaison de clés fournies en argument est présentes dans la KeyMap3d et faux
dans le cas contraire.V get(K clé1, L clé2, M clé3)
: Renvoie la valeur correspondant à la combinaison de clés fournie, ou null si cette combinaison de clés ne se trouve pas dans la KeyMap3d.put(K clé1, L clé2, , M clé3, V valeur)
: Ajoute une valeur associée au triplet de clés cle1,clé2,clé3
.Le type KeyMap3d<K,L,M,V>
est en réalité une simplification d'écriture de KeyMap2d<K,L,KeyMap<M,V>>
ce qui revient à avoir KeyMap<K,KeyMap<L,KeyMap<M,V>>>
.
Cela signifie qu'il est possible d'utiliser les fonctions d'usage du type KeyMap2d
et KeyMap
sur une variable de type KeyMap3d
. Par exemple la fonction size
va renvoyer le nombre d'éléments présents pour la première clé de type K
uniquement.
Ce type est identique à KeyMap
mais l'ordre dans lequel les clés ont été ajoutées est conservé. Cela signifie que lors du parcours des clés (avec la fonction keySet
) ou des valeurs (avec values
) on récupère les éléments dans le même ordre où ils ont été ajoutés.
Les fonctions d'usage sont identiques à celles de KeyMap.
Le type Cell permet de manipuler une représentation spatiale régulière de l'information géographique. Celui-ci est stocké sous forme matricielle. Il existe trois formes permettant de représenter l'espace de manière régulière et qui sont attribués au type Cell : le carré (ou rectangle), le triangle équilatéral, et l'hexagone régulier. Lorsque qu'une entité est caractérisée par un type Cell celle-ci ne peut avoir que des propriétés de type Double, Integer, Float, Byte ou Boolean.
Cellules régulières recouvrant l'ensemble d'un espace
getX()
: Retourne la position en abscisse de la matrice(ou nombre de colonnes).getY()
: Retourne la position en ordonnée de la matrice (ou nombre de lignes).getCentroid()
: Retourne un Point spécifiant la coordonnée projeté ou en latitude/longitude du centre de la cellule selon le type de référencement géographique utilisé.toPolygon()
: Retourne un Polygon de la forme de la cellule en coordonnées projetées ou en latitude/longitude selon le type de référencement géographique utilisé.distance(Cell cell)
: Retourne la distance avec une propriété de type Cell.distance(Geometry geom)
: Retourne la distance avec une propriété de type Geometry.