Page 1 sur 2
[..] Affecter des éléments d'un tableau à une variable
Posté : jeu. 02 sept. 2010 19:56
par pierrotm777
Bonjour,
J'essaie de comprendre l'utilisation des tableaux que j'ai franchement du mal à comprendre.
Pour cela je lis un fichier texte qui comporte des points gps, que je mais dans un tableau.
Pour tous les points gps de ce tableau, je voudrais tester la distance entre ces points GPS ($lat2,$lon2) et le point GPS où je me trouve ( $lat1,$lon1).
Le point GPS est lu toutes les 0.5s (timer) $lat1,$lon1 .
Mon script est pratiquement terminé mais actuellement, le programme ne vois que le dernier point.
Je voudrais que le programme teste en permanence si ma position se rapproche d'un des points listés dans le fichier zones.txt et si
c'est le cas visualiser la distance dans le input.
La distance d'alarme est définie par la variable $Distance2 = $Var[5] .
Je vous remercie de votre aide par avance.
Re: [..]Affectation des éléments d'un tableau à une variable
Posté : jeu. 02 sept. 2010 20:51
par moutelous
Bonsoir,
pierrotm777 a écrit :Mon script est pratiquement terminé mais actuellement, le programme ne vois que le dernier point
Regardez votre boucle For .... Next, elle ne fait qu'affecter des valeurs du tableau à des variables et ce jusqu'à la fin du tableau sans aucune exploitation de ces variables sauf effectivement pour le dernier point.
En fait l'algorithme doit être le suivant :
While 1
For
"chaque groupe de variables déterminant la position d'un radar"
"calculer la distance me séparant de ce radar"
Next
Wend
En espérant avoir été clair ....
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : ven. 03 sept. 2010 09:46
par pierrotm777
Oui, je pense, je vais essayer d'y réflaichir ,
Merci
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : ven. 03 sept. 2010 20:23
par pierrotm777
J'ai travaillé un peu le sujet, mais cela ne fait pas ce que je veux.
Le post 1 est mis à jour.
Quell est mon erreur SVP.
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : sam. 04 sept. 2010 22:09
par moutelous
Bonsoir,
pierrotm777 a écrit :mais cela ne fait pas ce que je veux
C'est à dire ?
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : dim. 05 sept. 2010 09:21
par pierrotm777
Et bien le tableau est relu régulièrement, alors qu'il suffirait qu'il soit lu une seule fois.
Enfin, il faudrait que ma boucle ne teste que la distance qui change entre les différents points du tableau, et si la distance est inférieure à 500 alors l'alarme se déclanche et indique la distance restante avant la position qui déclanche cette alarme.
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : mar. 28 sept. 2010 19:05
par pierrotm777
Désolé mais je ne m'en sort pas.
Si vous pouviez me guider svp ?
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : jeu. 30 sept. 2010 08:24
par Tlem
Je ne peut pas tester votre code, car je n'ai pas l'objet SDK RideRunner, mais voici quelques conseils rapides en passant :
1 - L'utilisation du Timer et le type de codage dans la boucle While !!!
Au lieu de mettre le code dans la boucle, utilisez plutôt la fonction
AdlibRegister.
Cela vous permettra d'activer/désactiver la comparaison de point plus facilement.
2 - Pour votre code de comparaison, vous pourriez (pour plus de facilité pour vous), utiliser la fonction
_ArrayFileToArray qui vous permettra de convertir votre fichier zones.txt directement en tableau 2D (ce qui devrait simplifier légèrement le code de votre boucle ainsi que la lecture de vos valeurs).

Re: [..] Affecter des éléments d'un tableau à une variable
Posté : jeu. 30 sept. 2010 11:45
par pierrotm777
Merci Tlem de votre intérêt pour mon problème.
Je vous propose mon script modifié de tel sorte qu'il n'a plus besoin de l'objet $RR .
Le point GPS du véhicule est simulé ici par le combo '$SelectPoi' qui donne 4 positions possibles.
Le post #1 est modifié, merci encore
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : jeu. 30 sept. 2010 23:37
par Tlem
Merci de ré-éditer votre premier message afin de ne laisser que le fichier joint.
Il est inutile d'avoir le code deux fois.
En ce qui concerne votre problème, je vais vous laisser travailler quand même un peut.
Je vous joint un code qui teste en boucle les coordonnées d'un point X (lat/lon) par rapport aux points de votre fichier zones.txt et qui affiche (dans la console de Scite) le texte lié au POI.
Amusez vous bien.

Re: [..] Affecter des éléments d'un tableau à une variable
Posté : ven. 01 oct. 2010 06:56
par pierrotm777
Je ne vois pas de fichier attaché à votre réponse !
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : ven. 01 oct. 2010 06:59
par Tlem
Oups !!!
Voici le code :
► Afficher le texte
Code : Tout sélectionner
#include <Math.au3>
#include <File.au3>
HotKeySet("{ESC}", "Terminate")
; Declaration de la latitude et de la longitude actuelle.
Global $lat = 44.872417
Global $lon = -0.565367
; Mise en tableau du fichier zones.txt
Global $aZones = _ArrayFileToArray(@scriptdir & "\zones.txt", ',')
;_ArrayDisplay($aZones, "Tableau des radars")
AdlibRegister("_IsNear", 2000)
;_IsNear($lat, $Lon, $aZones)
; Fonction de test latitude/longitude.
Func _IsNear()
Local $i
ConsoleWrite(@CRLF & @HOUR & "H" & @MIN & "M" & @SEC & "S" & " ---> ") ; Affiche le message dans la console de Scite
For $i = 0 To ubound($aZones) - 1
If Round(distHaversine($Lat, $Lon, $aZones[$i][0], $aZones[$i][1]),2) <= $aZones[$i][4] Then
; Renvoi dans la console le texte correspondant au POI.
ConsoleWrite($aZones[$i][6] & " ") ; Affiche le message dans la console de Scite
EndIf
Next
EndFunc
While 1
Sleep(50)
WEnd
;calcul de la distance entre deux points GPS selon la methode Haversine
func distHaversine($lat1, $lon1, $lat2, $lon2, $radius = 6378135)
$R = 6378135; // earth's mean radius in M (wikipedia)
$dLat = ($lat2-$lat1)/57.2957795130823
$dLon = _Radian($lon2-$lon1)
$lat1 = _Radian($lat1)
$lat2 = _Radian($lat2)
$R = $radius
$a = sin($dLat/2) * sin($dLat/2) + cos($lat1) * cos($lat2) * sin($dLon/2) * sin($dLon/2)
$c = 2 * atan(sqrt($a)/sqrt(1-$a))
$d = $R * $c
return $d
EndFunc
;====================================================================================================================
; Name : _ArrayFileToArray
; Description : Put an array file to an array
; Syntax : _ArrayFileToArray($hFile, $vDelimeter, $EmptyLine)
; Parameter(s) : $hFile - The file to proceed.
; $vDelimeter - One or more characters to use as delimiters (case sensitive)(Default is ';').
; $EmptyLine - 0 Do not return empty lines (Default).
; 1 Return the empty lines.
; $IndexBase - 0 Return an array that begin in index 0 (Default).
; 1 Return an array that begin in line 1 with elements numbers in index 0.
; Requirement(s) : File.au3
; Return value(s) : On Success - Returns array of file
; On Failure - Returns 0
; Author : Tlem <tlem at tuxolem dot fr>
; Note(s) : Inspired from a function made by SmOke_N
; http://www.autoitscript.com/forum/index.php?showtopic=26544&view=findpost&p=187403
; ====================================================================================================================
Func _ArrayFileToArray($hFile, $vDelimeter = ';', $EmptyLine = 0, $IndexBase = 0)
Local $aArray = '', $iMaxElement = 0, $iEmptyLines = 0, $iSecondElement = 0, $avArrayCount = 0
If Not _FileReadToArray($hFile, $aArray) Then Return 0
If $iEmptyLines <> 0 Then $iEmptyLines = 1
If $IndexBase <> 0 Then $IndexBase = 1
For $iLinesCount = 1 To $aArray[0]
If $aArray[$iLinesCount] <> '' Then
$iSecondElement = UBound(StringSplit($aArray[$iLinesCount], $vDelimeter, 1) - 1) - 1
If $iSecondElement > $iMaxElement Then $iMaxElement = $iSecondElement
EndIf
Next
If $EmptyLine = 0 Then
For $iLinesCount = 1 To $aArray[0]
If $aArray[$iLinesCount] = '' Then $iEmptyLines += 1
Next
EndIf
Local $avArray[$aArray[0] - $iEmptyLines + $IndexBase][$iMaxElement]
For $iCount = 1 To $aArray[0]
If $EmptyLine = 1 Then
$avArrayCount += 1
$aSplit = StringSplit($aArray[$iCount], $vDelimeter)
If $aSplit[0] - 1 > 0 Then
For $iCount2 = 1 To $aSplit[0]
$avArray[$avArrayCount - 1 + $IndexBase][$iCount2 - 1] = $aSplit[$iCount2]
Next
EndIf
ElseIf $aArray[$iCount] <> '' Then
$avArrayCount += 1
$aSplit = StringSplit($aArray[$iCount], $vDelimeter, 1)
If $aSplit[0] - 1 > 0 Then
For $iCount2 = 1 To $aSplit[0]
$avArray[$avArrayCount - 1 + $IndexBase][$iCount2 - 1] = $aSplit[$iCount2]
Next
EndIf
EndIf
Next
If $IndexBase = 1 Then $avArray[0][0] = $avArrayCount
Return $avArray
EndFunc ;==>_ArrayFileToArray
Func Terminate()
Exit 0
EndFunc
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : ven. 01 oct. 2010 19:12
par pierrotm777
Merci Tlem,
C'est bien ce qu'il me fallait.
Je vais tester avec un plus gros fichier pour voir
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : ven. 01 oct. 2010 21:07
par pierrotm777
Tlem,
Je vous joinds un fichier zones.txt complet (radars france 2009)
J'ai modifié mon script à partir de votre exemple.
Pourriez me dire si votre script fonctionne comme vous l'entendez.
Pour ma part, il semble trés lent .
Est possible d'utiliser plusieurs AdlibRegister , cela semble possible, mais la boucle principale prenant beaucoup de temp cpu, la mise à jour _LatLonUpdate ne se fait pas !
Par exemple:
AdlibRegister("_IsNear", 2000)
AdlibRegister("_LatLonUpdate", 500)
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : ven. 01 oct. 2010 21:40
par Tlem
Ben ... c'est ptet un chti peut normal non ?
36000 POI.
Vous imaginez un peut, que le script doit :
1 - Mettre en tableau spécial chaque élément de votre fichier, soit : 36000 X 7 = 252000
2 - Lire ce tableau ligne par ligne (36000) et prendre à chaque fois la longitude + la latitude pour calculer une valeur moyenne par rapport à la longitude + la latitude actuelle (et tout ca dans un délais de deux secondes sur mon script original) .
Vous ne trouvez pas que ca fait beaucoup ?
Dans votre cas précis, si vous devez lire chaque ligne du tableau, vous n'arriverez à rien de potable.
Pour cela, il vous faudra user d'un peut d'astuce et de bon sens.
Je vais vous mettre sur la voie :
Avez vous vraiment besoin de lire la totalité des lignes du tableau et d'y pratiquer chaque fois le calcul de proximité ?
Juste pour information, sur mon PC, la lecture du tableau de 36000 POI
$aZones sans aucune instruction dans la boucle, prend 4.7ms.
Si je rajoute la simple condition
If Int($aZones[$i][0]) > 1 Then ContinueLoop, hé bien nous passons de 5ms à 250ms et si je remplace par la fonction de test
distHaversine(), je passe à 5250ms.

Re: [..] Affecter des éléments d'un tableau à une variable
Posté : sam. 02 oct. 2010 10:25
par pierrotm777
Oui, je m'en doutais un peu !
Mon idée serait peut être de découper une fois pour toute les fichier en zones de 100km par exemple et de ne tester en suite
que dans la zone où l'on se trouve.
Qu'en pensez vous ?
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : sam. 02 oct. 2010 10:29
par Tlem
Ce sera moins simple au début, mais votre script n'en sera que plus rapide au final.

Re: [..] Affecter des éléments d'un tableau à une variable
Posté : dim. 03 oct. 2010 16:05
par pierrotm777
On pourrait par exemple découper le fichier en plusieurs, en prenant comme principe que chaque nom de fichier est du type:
partie entière latitude partie entière longitude . txt
soit pour un fichier comme suivant:
Code : Tout sélectionner
[color=#FF0000]50[/color].17353,[color=#FF0000]3[/color].24325,300,60,500,M,"ZONE_DANGEREUSE_0"
[color=#FF0000]50[/color].18552,[color=#FF0000]3[/color].34339,300,60,500,M,"ZONE_DANGEREUSE_0"
[color=#FF0000]50[/color].21,[color=#FF0000]3[/color].3865,300,60,500,M,"ZONE_DANGEREUSE_0"
[color=#FF0000]50[/color].24937,[color=#FF0000]3[/color].03142,300,60,500,M,"ZONE_DANGEREUSE_0"
[color=#FF0000]50[/color].2842,[color=#FF0000]3[/color].97474,300,60,500,M,"ZONE_DANGEREUSE_0"
[color=#FF0000]50[/color].34262,[color=#FF0000]3[/color].97068,300,60,500,M,"ZONE_DANGEREUSE_0"
5003.txt
Le problème est que chaque partie entière peut être soit positive soit négative en fonction de sa position Gps sur le globe !
De plus avant la création des zones, je ferais bien un tri du fichier par rapport à la première colonne .
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : dim. 03 oct. 2010 22:18
par Tlem
La fragmentation des POI en plusieurs fichiers n'est pas mal, mais je pense qu'elle ne doit pas être en relation avec les coordonnées.
Vous pouvez, par exemple séparer les radars en fonction de leur vitesse, mais dans ce cas cela va compliquer leur gestion.
J'avais plutôt à l'idée de ce concentrer sur une partie significative des coordonnées.
Lorsque l'on prend pour exemple une longitude de 50.17353°, le fait de ce déplacer va modifier ce nombre et plus particulièrement la dernière partie de celui-ci.
En règle générale, il est très rare de prévenir de la présence d'un POI qui ce trouve en dehors d'un périmètre de quelques kilomètres (1 à 5 max).
Donc l'idée serait de voir ce que représente un déplacement de 5 Km Ouest sur la valeur de la longitude cité précédemment.
Je n'ai pas l'information exacte, mais d'après mes petits tests, je dirait que pour 5 Km, le chiffre significatif à prendre en considération, est le deuxième après la virgule.
En ce basant sur la longitude de 50.17353°, si j'augmente ce nombre de 0,05 soit 50.22353°, j'obtiens un déplacement approximatif sur Google Map de 5 Km et des brouettes.
Donc dans ce cas, il suffit de comparer brièvement la partie significative des coordonnées à comparer et de prendre la décision de faire le test de la distance entre les points ou non.
En reprenant une partie de votre tableau, voici ce que je prendrais en considération :
Code : Tout sélectionner
[color=#FF0000]50.17[/color]353,[color=#FF0000]3.24[/color]325,300,60,500,M,"ZONE_DANGEREUSE_0"
[color=#FF0000]50.18[/color]552,[color=#FF0000]3.34[/color]339,300,60,500,M,"ZONE_DANGEREUSE_0"
[color=#FF0000]50.24[/color]937,[color=#FF0000]3.03[/color]142,300,60,500,M,"ZONE_DANGEREUSE_0"
De plus, si le tableau est trié par ordre croissant, je peut rajouter un test afin d'éviter de lire la suite du tableau si je rencontre une valeur supérieur de 5 Km à mes coordonnées actuelles.
Re: [..] Affecter des éléments d'un tableau à une variable
Posté : lun. 04 oct. 2010 03:04
par GaRydelaMer
Bonsoir
vous allez dire que je reviens encore avec ca, mais bon je me lance !!
Pourquoi pas utiliser ADO ?.
J'ai fais un test avec ton fichier les 38000 POI:
► Afficher le texte
Code : Tout sélectionner
Global Const $adUseClient = 3
Global Const $adOpenDynamic = 2
Global Const $adLockOptimistic = 3
Global Const $adCmdTable = 2
Local $begin = TimerInit(), $dif
Global $aZones, $oConn = ObjCreate("ADODB.Connection")
With $oConn
.CursorLocation = $adUseClient
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & @ScriptDir & _
";Extended Properties=""text;HDR=NO;FMT=Delimited"";"
.Open
EndWith
Global $oRS = ObjCreate("ADODB.Recordset")
$oRs.Open("zones.txt", $oConn, $adOpenDynamic, $adLockOptimistic, $adCmdTable)
;~ Affiche le nom des champs
For $Field In $oRS.Fields
ConsoleWrite("Name=" & $Field.Name & @LF)
Next
$oRs.Sort = "F7 desc, F1, F2"
;~ $aZones = $oRS.GetRows()
;~ _ArrayDisplay($aZones)
$oRS.Filter = "F1 >= 44.87 AND F1 <= 44.88 AND F2 >= -0.5 AND F2 <= 0"
$aZones = $oRS.GetRows()
$dif = TimerDiff($begin)
ConsoleWrite("Time Difference " & $dif & @LF)
_ArrayDisplay($aZones)
$begin = TimerInit()
$oRS.Filter = "F1 >= 45.87 AND F1 <= 45.88 AND F2 >= -0.5 AND F2 <= 0"
$aZones = $oRS.GetRows()
$dif = TimerDiff($begin)
ConsoleWrite("Time Difference " & $dif & @LF)
_ArrayDisplay($aZones)
$begin = TimerInit()
$oRS.Filter = "F1 >= " & Round($lat1, 2) - 0.01 & " AND F1 <= " & Round($lat1, 2) + 0.01 & _
" AND F2 >= " & Round($lon1, 2) - 0.01 & " AND F2 <= " & Round($lon1, 2) + 0.01
ConsoleWrite($oRS.Filter & @LF)
ConsoleWrite($oRs.RecordCount & @LF)
If $oRs.EOF Then
ConsoleWrite("Aucun radar dans le coin :-)" & @LF)
Else
$aZones = $oRS.GetRows()
EndIf
$dif = TimerDiff($begin)
ConsoleWrite("Time Difference " & $dif & @LF)
_ArrayDisplay($aZones)
$oRS.Close
$oConn.Close
; Mise en tableau du fichier zones.txt
$begin = TimerInit()
Global $aZones1 = _ArrayFileToArray(@ScriptDir & "\zones.txt", ',')
$dif = TimerDiff($begin)
ConsoleWrite("Time Difference " & $dif & @LF)
Exit
Le truc ici est de filtrer rapidement les données, la je filtre uniquement sur le 1er champ mais on peut multiplier les conditions du filtre.
Par exemple:
Un dernier point, attention si le filtre renvoie aucune valeur la fonction GetRows() renvoie une erreur.
Facile à gérer:
► Afficher le texte
Code : Tout sélectionner
$oRS.Filter = "F1 >= " & Round($lat1, 2) - 0.01 & " AND F1 <= " & Round($lat1, 2) + 0.01 & _
" AND F2 >= " & Round($lon1, 2) - 0.01 & " AND F2 <= " & Round($lon1, 2) + 0.01 & _
" AND F7 Like 'RADAR_FIXE%'"
ConsoleWrite($oRS.Filter & @LF)
If $oRs.EOF Then
ConsoleWrite("Aucun radar dans le coin :-)" & @LF)
Else
ConsoleWrite($oRs.RecordCount & " Radar(s) en vue" & @LF)
$aZones = $oRS.GetRows()
EndIf
Un autre dernier point c'est plus long à ouvrir:
Pour trier un tableau Type de radar décroissant puis par latitude, longitude croissant:
le résultat sur ma machine:
Name=F1
Name=F2
Name=F3
Name=F4
Name=F5
Name=F6
Name=F7
Time Difference 834.542378989508
Time Difference 29.2523211748979
Time Difference 4029.22913387037
On voit que même en ouvrant la connexion on est plus rapide que le parcours du tableau. dans mon test je filtre 2 fois le tableau, le 1er je compte l'ouverture de la connexion ensuite en 29 ms je le filtre sur les autres valeurs.
26 valeurs entre 44.87 et 44.88
32 valeurs entre 45.87 et 45.88
Avec le tri:
Name=F1
Name=F2
Name=F3
Name=F4
Name=F5
Name=F6
Name=F7
Time Difference 32249.4923237451
Time Difference 53.4419877386651
F1 >= 44.86 AND F1 <= 44.88 AND F2 >= -0.58 AND F2 <= -0.56
6 enregstrements
Time Difference 288.390842970266
Time Difference 4707.70279462893