Peut-être est-il complexe, mais je ne vois pas quoi supprimer.
Je place ci-après le même fonction, mais sans la protection contre un trop grand déplacement. Peut-être te paraitra-t-elle plus simple (les parties en rouge ne concernent que l'affichage des coordonnées) :
Cordialement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 procedure TAffCarte.ZoneAffMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); {Il semble que sur l'écran tactile 7" de mon Raspberry, les premières données de "OnMove" obtenues par toucher de l'écran ne soient pas correctes. Un petit compteur permet de ne pas les prendre en compte.} var Da, Xa, Ya: Extended; begin if ssLeft in Shift then begin Xa:= X*cosCap+Y*sinCap; // cosCap et sinCap représente la matrice de rotation à appliquer aux ... Ya:= Y*cosCap-X*sinCap; // ... déplacements quand la carte est présentée Cap en haut au lieu du Nord Depl.X:= (CurPos0.X-Xa)/kZoom; // Depl = déplacement de la souris en pixels Depl.Y:= (CurPos0.Y-Ya)/kZoom; if CmptDepl > 1 then begin TotDepl.X:= TotDepl.X+Depl.X; TotDepl.Y:= TotDepl.Y+Depl.Y; CurPos0.X:= Xa; CurPos0.Y:= Ya; Longitude:= LonTuileG+(DemiTuile+TotDepl.X)*(LonTuileD-LonTuileG)/DimTuile; if Longitude > 180 then Longitude:= Longitude-360 else if Longitude < -180 then Longitude:= Longitude+360; Latitude:= LatTuileB+(DemiTuile-TotDepl.Y)*(LatTuileH-LatTuileB)/DimTuile; if MajAff then // MajAff est une protection pour ne pas ré-entrer dans le bloc "begin ... end" ... begin // ci-après si elle n'est pas terminée. Mis à faux dans MaJ_Carte et remis à vrai à la fin de "DoOnPaint" MaJ_Carte(PointF(TotDepl.X, TotDepl.Y)); // C'est là où je fais mon choix des dalles à charger et afficher clInfPos:= VGABlue; TxtGPS:= Choix_Aff_Coord(Latitude, Longitude, TypeCoord); ZoneAff.DoOnPaint; // Transformation du bitmap de la carte en Texture OpenGL end; end; Inc(CmptDepl); end; end;
Pierre
NOTA : Tout ceci fonctionne très bien si je fais de petits déplacements avec la souris : les algorithmes de chargement et placement des dalles sont donc corrects.
Lorsque ce n'est pas le GPS qui commande le déplacement de la carte, c'est effectivement la souris qui sert à placer à l'écran la partie de la carte que je veux voir.
Dans le cas où c'est le GPS qui commande, je lui demande effectivement de placer le point où il se trouve au centre de l'écran.
Si je fais un déplacement avec la souris, je place ce que je veux voir là où je le veux le voir.
Toutes mes tuiles ont la même dimension : 256 x 256 pixels². La carte est toujours composée de 5 x 5 = 25 tuiles. Lorsque le déplacement nécessite de nouvelle dalles, je déplace, dans la carte, celles qui doivent y rester et je place aux endroits qui sont de ce fait vides les nouvelles dalles.
Mon affichage ne présente qu'une surface de 1024 x 600 pixels et ne nécessiterait normalement que 4 x 2.5 dalles. Mais du fait que la présentation peut tourner, dans le pire cas : 45°, si je veux que mon écran soit toujours rempli de dalle, cela m'oblige à en avoir 25, sinon, j'aurais des blancs dans les angles.
Je vais aller voir ça.
Cordialement.
Pierre
Salut
Donc si j'ai bien compris ton fichier OSM est un fichier XML qui détermine la longitude et la latitude minimum et maximum de ta carte (ou dalle).
A la lecture de ce fichier tu connais donc le nombre maximum de tuile horizontale et verticale.
De combien de tuiles (ou images) en moyenne est constituée une carte avec le niveau de zoom 17/18 comme mentionné dans l'article, dans ton cas (pour connaitre l'occupation en mémoire) ?
je dirais que le soucis soit plus dans ta méthode "MAJ_Carte" que ton déplacement en lui même. D'ailleurs pourquoi utilises tu TotDeplX/Y plus tôt que la longitude et latitude ? Tu refais les calculs dans cette procédures ?
Je pense que c'est le temps de chargement de tes tuiles la problématique, ce qui produit au final un saut dans les événements (certain ne sont pas pris en compte) ce qui fausse les données et cause donc des erreurs.
Utilises tu un Thread pour les chargées ? ou as tu déja préchargé toutes (ou une grosse partie) des tuiles au démarrage ?
Une solution serais de charger au minimum une dalle de 8x8 au lieu de 5x5 (vu que tu utilises OpenGL , il ne devrais pas avoir une baisse importante des performances.
Je vais essayé de faire un petit projet de test simple cet après-midi. J'ai du temps à perdre
A+
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Mon "fichier OSM" n'est pas un fichier XML., c'est un ensemble de fichier *.jpg que j'obtiens à partir du logiciel "MOBAC" avec l'option de chargement "OSMTracker tile storage". L'ensemble de ces fichiers est réparti dans plus sous-répertoires dont le répertoire chapeau est le nom de ma carte, par exemple "IdF_NO" (pour Ile de France Nord Ouest). L'architecture de ces répertoires est celle que me donne MOBAC : le premier sous-répertoire est l'indice de zoom (pour ce qui me concerne, j'utilise les indices 9, 11, 13 et 15). Le deuxième niveau de sous-répertoire est l'indice de la longitude et, dans ce répertoire, sont les fichiers (tuiles) Lyy.jpg où Lyy sont les indices de latitude et dont la taille est fixe et vaut 256 x 256 pixels².
Mes cartes avec le niveau de zoom 15 comportent entre 50 à 100 longitudes; chacune des longitudes comportant de 50 à 100 latitudes. Donc chaque carte comporte de 2500 à 10000 tuiles. Je n'en ai jamais que 25 + une (celle en chargement) en mémoire vive.
Oui, je pense que cela vient de là, mais je n'arrive pas à le mettre en évidence.
Je sais que j'avais passé pas mal de temps pour choisir ma méthode de recherche de carte entre Indices --> Coordonnées ou Coordonnées -> Indices. C'était compliqué ; il faut que je retrouve mon cheminement (qui n'a pas forcément été le bon).
C'est certainement cela, mais comme dit plus haut, je n'arrive pas à le mettre en évidence.
Non, les cartes ne sont pas pré-télechargées et je n'utilise pas de thread pour le faire. J'en utilise déjà deux : l'un pour l'acquisition des données GPS et l'autre pour l'acquisition des données du compas magnétique 3 axes. N'étant pas sûr que ces threads utilisent les divers cœurs mis à disposition, cela ne ferait que de découper en tranches les différentes activités.
NOTA : Le problème de chargement des dalles existe alors même que je ne mets pas les threads en route.
Il faut trouver le temps de les télécharger ... ce qui me pose déjà problème avec 5 x 5 ???
merci beaucoup pour ta participation .
Cordialement.
Pierre
Ça y est, je pense avoir retrouvé la raison. De toutes façons, il y a une relation bi-univoque entre un fichier OSM et une latitude et une longitude, et, dans ma recherche de tuiles, affichage des coordonnées, j'utilise les deux sens de recherches. Mais à la fin, lorsqu'il s'agit de rechercher un fichier, j'ai choisi les indices car il me suffit d'incrémenter ou décrémenter cet indice pour trouver le nom du fichier adjacent.
Cordialement.
Pierre
salut
donc le principe est de placer la longitude et le latitude au centre de l’écran
et ensuite replacer les tuile qui sont autour
les coordonné de ta tuile dans tes répertoire corresponde au centre de la tuile ou à la parti supérieur gauche de la tuile ?
je suppose donc que les tuiles correspondent à un pas qui est différent selon le zoom que tu utilise
à partir de là, ce n'est pas compliqué de chercher les tuiles aux alentours
Prend ton ecran comme une grille divisé en Carre
[
Blaise PascalNous souhaitons la vérité et nous trouvons qu'incertitude. [...]
Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
PS : n'oubliez pas le tag
Ok, c'était pour avoir une vision de la taille des données.
Je galère juste avec les indices, pour trouver une solution performante alors avec les coordonnées, je n'imagine même pas (et en plus je n'ai pas les données nécessaires pour ce calcul)
Lorsque tu dis "télécharger" / "pré-télechargées" tes images ne sont pas stockées sur ton disque ? tu vas les récupérer sur un serveur ?
Tu peux peut-être utiliser ton Thread pour l'aquisition des données GPS et faire le chargement des tuiles dedans, non ?
EDIT :
Un des problème que j'ai remarqué cet après-midi c'est le ratio de déplacement entre "tuiles" et pixels pour que l'affichage ne joue pas à saute mouton et qu'il reste fluide.
Le deuxième problème que je vois venir c'est quand il y aura une rotation en même temps, c'est pour cela que je suggérai un tableau de 8x8 au lieu de 5x5
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Dans le cas où c'est le GPS qui me donne l'information, oui je place ce point au milieu de l'écran.
Dans le cas où c'est moi qui me promène sur une carte, je place le couple latitude/longitude là où bon me semble.
Dans les deux cas, j'entoure cette tuile des tuiles adjacentes
C'est le point haut/gauche de la tuile.
Oui.
Ce n'est effectivement pas compliqué et mes méthodes le font très bien ... sauf que, de temps en temps et non systématiquement (du moins je n'ai pas réussi à le mettre en évidence) cela se passe mal. J'ai quand même réussi à avancer un petit peu.
Lorsque je dois modifier les tuiles présentes, dans la carte (5 x 5 tuiles), je décale d'une tuile (dans le sens voulu) celles qui doivent être conservées et je charge les nouvelles tuiles pour les placer au endroits devenus vides.
Apparemment, le décalage fonctionne bien. C'est le chargement/affichage des nouvelles tuiles qui se fait mal : comme s'il ne se faisait pas et que ce sont les anciennes tuiles qui restent là où elles auraient dues être remplacées.
Cordialement.
Pierre
J'ai schématisé le problème comme je le vois
Donc maintenant c'est trouver le bon algorithme pour que le déplacement puisse se faire au pixel près en sélectionnant les bon indices de tuiles et éviter le saut de mouton, de mon coté je n'ai pas encore trouvé la formule magique. Il faut que je me creuse encore un peu les méninges.
Je pense qu'il faut calculer un "Delta" afin d'ajuster la position au pixel avec le centrage du tampon par rapport à la zone d'affichage
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Deuxième petit dessin, en centrant le tampon à la zone d'affichage, il me semble bien que du coup, il faille charger des tuiles supplémentaires pour que l'affichage de la carte soit totale, non ? ou je me plante carrément, dans ma logique ?
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
C'est exactement ce que je fais.
Le calcul du déplacement au pixel près est résolu (même avec la rotation dans laquelle tu m'as déjà aidé ...) le problème est "apparemment" le chargement suivi du placement des nouvelles tuiles. Si je me déplace lentement, cela se passe toujours bien. Malheureusement, si je vais plus vite, cela se passe mal. peut-être que sans que je le voie, le sache, un autre déplacement (ou non) se fait. C'est ce que j’essaie de mettre en évidence sans pour l'instant y arriver.
Voici la procédure de chargement/placement des nouvelles tuiles. Ce n'est jamais que 8 fois la même chose avec des indices de placement fonction de la direction vers laquelle je me déplace. Unitairement et en allant lentement, toutes fonctionnent.
Cordialement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273 procedure TAffCarte.Charge_Tuiles(Tuile: TRefCarte; Cas: Integer; var Decal, TotDecal: TPointF); var i, j: Integer; NomCarte, NomTuile: String; begin case Cas of 0, 9: begin // Recréation de toutes les tuiles for i:= 0 to 4 do for j:= 0 to 4 do with Tuile do begin {Chargement d'un panel de 25 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+j-2, OSMLon+i-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, DimTuile*j, DimTuile*(i+1), DimTuile*(j+1)), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+i-2)+SepRep+IntToStr(OSMLat+j-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, DimTuile*j, DimTuile*(i+1), DimTuile*(j+1)), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; end; 1: begin // Augmentation de la longitude BmpCarte.CanvasBGRA.CopyRect(Rect(0, 0, 4*DimTuile, 5*DimTuile), BmpCarte, Rect(DimTuile, 0, 5*DimTuile, 5*DimTuile)); for j:= 0 to 4 do // Bandeau vertical droit with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+j-2, OSMLon+2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(4*DimTuile, DimTuile*j, 5*DimTuile, DimTuile*(j+1)), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+2)+SepRep+IntToStr(OSMLat+j-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(4*DimTuile, DimTuile*j, 5*DimTuile, DimTuile*(j+1)), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; Decal.X:= Decal.X-256; TotDecal.X:= TotDecal.X-256; end; 2: begin // Diminution de la longitude for i:= 4 downto 1 do BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*(i), 0, DimTuile*(i+1), 5*DimTuile), BmpCarte, Rect(DimTuile*(i-1), 0, DimTuile*(i), 5*DimTuile)); for j:= 0 to 4 do with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+j-2, OSMLon-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(0, DimTuile*j, DimTuile, DimTuile*(j+1)), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon-2)+SepRep+IntToStr(OSMLat+j-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(0, DimTuile*j, DimTuile, DimTuile*(j+1)), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; Decal.X:= Decal.X+256; TotDecal.X:= TotDecal.X+256; end; 3: begin // Diminution de la latitude BmpCarte.CanvasBGRA.CopyRect(Rect(0, 0, DimTuile*5, DimTuile*4), BmpCarte, Rect(0, DimTuile, DimTuile*5, DimTuile*5)); for i:= 0 to 4 do with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+2, OSMLon+i-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, DimTuile*4, DimTuile*(i+1), DimTuile*5), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+i-2)+SepRep+IntToStr(OSMLat+2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, DimTuile*4, DimTuile*(i+1), DimTuile*5), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; Decal.Y:= Decal.Y-256; TotDecal.Y:= TotDecal.Y-256; end; 4: begin // Augmentation de la latitude for j:= 4 downto 1 do BmpCarte.CanvasBGRA.CopyRect(Rect(0, DimTuile*j, DimTuile*5, DimTuile*(j+1)), BmpCarte, Rect(0, DimTuile*(j-1), DimTuile*5, DimTuile*j)); for i:= 0 to 4 do with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat-2, OSMLon+i-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, 0, DimTuile*(i+1), DimTuile), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+i-2)+SepRep+IntToStr(OSMLat-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, 0, DimTuile*(i+1), DimTuile), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; Decal.Y:= Decal.Y+256; TotDecal.Y:= TotDecal.Y+256; end; 5: begin // Augmentation de la longitude et diminution de la latitude BmpCarte.CanvasBGRA.CopyRect(Rect(0, 0, 4*DimTuile, 4*DimTuile), BmpCarte, Rect(DimTuile, DimTuile, 5*DimTuile, 5*DimTuile)); for j:= 0 to 3 do // Bandeau vertical droit with Tuile do begin {Chargement d'un panel de 4 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+j-2, OSMLon+2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(4*DimTuile, DimTuile*j, 5*DimTuile, DimTuile*(j+1)), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+2)+SepRep+IntToStr(OSMLat+j-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(4*DimTuile, DimTuile*j, 5*DimTuile, DimTuile*(j+1)), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; for i:= 0 to 4 do // Bandeau horizontal inférieur with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+2, OSMLon+i-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, DimTuile*4, DimTuile*(i+1), DimTuile*5), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+i-2)+SepRep+IntToStr(OSMLat+2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, DimTuile*4, DimTuile*(i+1), DimTuile*5), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; Decal.X:= Decal.X-256; Decal.Y:= Decal.Y-256; TotDecal.X:= TotDecal.X-256; TotDecal.Y:= TotDecal.Y-256; end; 6: begin // Augmentation de la longitude et augmentation de la latitude for j:= 4 downto 1 do BmpCarte.CanvasBGRA.CopyRect(Rect(0, DimTuile*j, DimTuile*4, DimTuile*(j+1)), BmpCarte, Rect(DimTuile, DimTuile*(j-1), DimTuile*5, DimTuile*j)); for j:= 1 to 4 do // Bandeau vertical droit with Tuile do begin {Chargement d'un panel de 4 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+j-2, OSMLon+2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(4*DimTuile, DimTuile*j, 5*DimTuile, DimTuile*(j+1)), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+2)+SepRep+IntToStr(OSMLat+j-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(4*DimTuile, DimTuile*j, 5*DimTuile, DimTuile*(j+1)), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; for i:= 0 to 4 do // Bandeau horizontal haut with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat-2, OSMLon+i-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, 0, DimTuile*(i+1), DimTuile), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+i-2)+SepRep+IntToStr(OSMLat-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, 0, DimTuile*(i+1), DimTuile), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; Decal.X:= Decal.X-256; Decal.Y:= Decal.Y+256; TotDecal.X:= TotDecal.X-256; TotDecal.Y:= TotDecal.Y+256; end; 7: begin // Diminution de la longitude et diminution de la latitude for i:= 0 to 4 do BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile, DimTuile*(i-1), DimTuile*5, DimTuile*i), BmpCarte, Rect(0, DimTuile*i, DimTuile*4, DimTuile*(i+1))); for i:= 0 to 4 do // Bandeau horizontal bas with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+2, OSMLon+i-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, DimTuile*4, DimTuile*(i+1), DimTuile*5), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+i-2)+SepRep+IntToStr(OSMLat+2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, DimTuile*4, DimTuile*(i+1), DimTuile*5), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; for j:= 0 to 3 do // Bandeau vertical gauche with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+j-2, OSMLon-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(0, DimTuile*j, DimTuile, DimTuile*(j+1)), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon-2)+SepRep+IntToStr(OSMLat+j-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(0, DimTuile*j, DimTuile, DimTuile*(j+1)), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; Decal.X:= Decal.X+256; Decal.Y:= Decal.Y-256; TotDecal.X:= TotDecal.X+256; TotDecal.Y:= TotDecal.Y-256; end; 8: begin // Diminution de la longitude et augmentation de la latitude for i:= 4 downto 1 do BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*(i), DimTuile, DimTuile*(i+1), 5*DimTuile), BmpCarte, Rect(DimTuile*(i-1), 0, DimTuile*(i), 4*DimTuile)); for i:= 0 to 4 do // Bandeau horizontal haut with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat-2, OSMLon+i-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, 0, DimTuile*(i+1), DimTuile), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+i-2)+SepRep+IntToStr(OSMLat-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(DimTuile*i, 0, DimTuile*(i+1), DimTuile), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; for j:= 1 to 4 do // Bandeau vertical gauche with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} NomCarte:= Fch_Tuile(OSMLat+j-2, OSMLon-2, Tuile); if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(0, DimTuile*j, DimTuile, DimTuile*(j+1)), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon-2)+SepRep+IntToStr(OSMLat+j-2)+'.jpg'; if FileExists(NomTuile) then begin BmpTuile.LoadFromFile(NomTuile); BmpCarte.CanvasBGRA.CopyRect(Rect(0, DimTuile*j, DimTuile, DimTuile*(j+1)), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); end; end; end; Decal.X:= Decal.X+256; Decal.Y:= Decal.Y+256; TotDecal.X:= TotDecal.X+256; TotDecal.Y:= TotDecal.Y+256; end; end; Carte:= BmpCarte.Texture; end;
Pierre
Une piste, lorsque tu vas doucement tout va bien. Par exemple pour un déplacement vers la droite, tu charges bien 1 colonne au fur et à mesure.
Mais quand tu vas vite, est-ce que tu charges plus de colonnes ? si tu sautes plus d'une tuile en un mouvement de souris, il te faudra donc charger le même nombre de colonne. Il ne me semble pas que tu prennes ce cas dans "Charge_Tuiles" à moins que ce soit le cas 0 et 9 ?
Serait-il possible de voir ce qui se cache derrière ta procedure "MaJ_Carte" ?
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Oui.
Le problème est que dans ce que j'appelle me déplacer vite, la valeur du déplacement n'atteint même pas la dimension d'un demi-tuile. Dans mes procédures, je ne me décale jamais plus que du pas d'une tuile.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 procedure TAffCarte.MaJ_Carte(Dec: TPointF); var Cas: Integer; begin Cas:= 0; if (Abs(Dec.X) > MaxDecal) or (Abs(Dec.Y) > MaxDecal) then Cas:= 9 else if (Dec.X > SeuilDecal) and (Dec.Y < SeuilDecal) and (Dec.Y > -SeuilDecal) then Cas:= 1 else // Augmentation de la longitude if (Dec.X < -SeuilDecal) and (Dec.Y < SeuilDecal) and (Dec.Y > -SeuilDecal) then Cas:= 2 else // Diminution de la longitude if (Dec.Y > SeuilDecal) and (Dec.X < SeuilDecal) and (Dec.X > -SeuilDecal) then Cas:= 3 else // Diminution de la latitude if (Dec.Y < -SeuilDecal) and (Dec.X < SeuilDecal) and (Dec.X > -SeuilDecal) then Cas:= 4 else // Augmentation de la latitude if (Dec.X >= SeuilDecal) and (Dec.Y >= SeuilDEcal) then Cas:= 5 else // Augmentation de la longitude et diminution de la latitude if (Dec.X >= SeuilDecal) and (Dec.y <= -SeuilDecal) then Cas:= 6 else // Augmentation de la longitude et augmentation de la latitude if (Dec.X <= -SeuilDecal) and (Dec.Y >= SeuilDecal) then Cas:= 7 else // Diminution de la longitude et diminution de la latitude if (Dec.X <= -SeuilDecal) and (Dec.Y <= -SeuilDecal) then Cas := 8; // Diminution de la longitude et augmentation de la latitude if (Cas > 0) and MajAff then begin MajAff:= False; Tuile:= Infos_Tuiles(Latitude, Longitude, ZoomCarte); Charge_Tuiles(Tuile, Cas, Depl, TotDepl); end; end;Cordialement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 function Infos_Tuiles(La, Lo: Extended; Zm: Integer): TRefCarte; begin with Result do try OSMLat:= IndYOSM(La, Zm); // Indice du fichier tuile pour cette latitude OSMLon:= IndXOSM(Lo, Zm); // Indice du sous-répertoire des longitudes RepZoom:= Index_Zoom(LstZoom, Zm); // Nom du sous-répertoire des zoom Nom:= Fch_Tuile(OSMLat, OSMLon, Result); // Nom du fichie tuile Zoom:= Zm; // Zoom Lon:= Lo; // Longitude (en degrés décimaux) Lat:= La; // Latitude (en degrés décimaux) LatTuileH:= LatOSM(OSMLat, Zm); // Latitude du bord haut de la tuile LatTuileB:= LatOSM(OSMLat+1, Zm); // Latitude du bord bas de la tuile LonTuileG:= LonOSM(OSMLon, Zm); // Longitude du bord gauche de la tuile LonTuileD:= LonOSM(OSMLon+1, Zm); // Longitude du bord Droit de la tuile DeplX:= Round(DimTuile*(Lo-LonTuileG)/(LonTuileD-LonTuileG)); // Position en X dans la tuile DeplY:= Round(DimTuile*(LatTuileH-La)/(LatTuileH-LatTuileB)); // Position eh Y dans la tuile except end; end;
Pierre
Je pense avoir identifié le problème. Cela se passe si je sors d'une tuile par un angle mais que je ne passe pas le seuil en même temps en Y et en Y (donc méthode foireuse ). Je pense que je tiens le bon bout ...
Cordialement.
Pierre
Salut Pierre,
j'ai regardé d'un peu plus près tes méthodes, il y a pas mal de petites choses qui peuvent être optimisée pour réduire les temps de latence. Comme la génération des noms de fichiers, certaine parties ou tu utilises BGRABitmap pour déplacer les tuiles.
De plus gérer les diagonales, est à mon sens en trop. Un test Haut/Bas avec chargement des tuiles au besoins, suivis d'un test Gauche/Droite avec chargement des tuiles au besoins devrait suffire. En prenant en compte un nombre différents pour l'horizontale (tuiles en colonne) qui devra charger une tuile de plus celle du coin haut ou bas, si le déplacement vertical a eu lieu avant)
Une chose qui serait bien serait que tu sépares le système de gestion et d'affichage des tuiles dans des classes séparés, plus tôt que de tout mettre dans ta "form". Cela permettrait de mieux optimisée les choses et il serait beaucoup plus facile de faire évoluer le code au besoins.
Je pense également qu'un accès aux tuiles par indice plus tôt que par coordonnées serait aussi bénéfique en terme de performances.
Autres truc l'utilisation d'un thread pour le chargement, même si tu en as déjà deux devrait aider, à mon sens.
Ton problème, rentre en partie sur un sujet que je souhaitais intégrer à mon projet J'ai donc commencé à coder quelques classes dans ce sens. Dès que je finis je posterai les sources et une petite démo de test.
Petite question en attendant, pourrais tu me donner les coordonnées GPS des limites de cette image (tu l'avais mis pour le problème de rotation). Afin que je puisse faire deux, trois calculs de bases. J'ai généré des tuiles de 128 pixels soit 10x10 pour les tests de mon code (à petite échelle )
Merci
A+
Jérôme
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Cette image est composée de 5 x 5 dalles de 256 x 256 pixels chacune.
Les formules suivantes donnent la longitude et la latitude du coin haut/gauche d'une dalle.
Longitude = 360 x N / 2Z - 180 en °décimaux où N est l'indice en longitude de la dalle et Z l'indice de zoom
Latitude = ArcTan(SinH(n)) x 180 / PI en ° décimaux où N est l'indice en latitude de la dalle et Z l'indice de zoom
avec n = (1 - 2 x N / 2Z) x PI
référence de la dalle du coin haut/gauche de l'image :
- Nlongitude = 16579 -> Lo = 002.142333984... Est
- Nlatitude = 11252 -> La = 049.009050809... Nord
- Z = 15
Cordialement.
Pierre
Bonjour,
Joli travail d'illustration BeanzMaster.
Petite contribution. Pour éviter de gérer les déplacements des tuiles conservées, il est possible de les adresser via un tampon doublement circulaire (avec une puissance de 2 ce serait encore plus rapide) avec un double indice de tuile centrale (iX, iY) qui seul se déplace.
Salutations
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)
J'ai fait un "profilage" des temps d'exécution de chacune des tâches dans le chargement/placement des nouvelles tuiles.
Au résultat :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 1: begin // Augmentation de la longitude T1:= Time; BmpCarte.CanvasBGRA.CopyRect(Rect(0, 0, 4*DimTuile, 5*DimTuile), BmpCarte, Rect(DimTuile, 0, 5*DimTuile, 5*DimTuile)); T2:= Time; Memo1.Lines.Add('Decal '+Format('%.1f', [(T2-T1)*86400000])); for j:= 0 to 4 do // Bandeau vertical droit with Tuile do begin {Chargement d'un panel de 5 cartes de 256 x 256 pixels²} T3:= Time; NomCarte:= Fch_Tuile(OSMLat+j-2, OSMLon+2, Tuile); T4:= Time; if NomCarte = '' then BmpCarte.CanvasBGRA.CopyRect(Rect(4*DimTuile, DimTuile*j, 5*DimTuile, DimTuile*(j+1)), BmpVide, Rect(0, 0, DimTuile, DimTuile)) else begin NomTuile:= 'Cartes'+SepRep+NomCarte+IntToStr(Zoom)+SepRep+IntToStr(OSMLon+2)+SepRep+IntToStr(OSMLat+j-2)+'.jpg'; if FileExists(NomTuile) then begin T5:= Time; BmpTuile.LoadFromFile(NomTuile); T6:= Time; BmpCarte.CanvasBGRA.CopyRect(Rect(4*DimTuile, DimTuile*j, 5*DimTuile, DimTuile*(j+1)), BmpTuile, Rect(0, 0, DimTuile, DimTuile)); T7:= Time; Memo1.Lines.Add('NomC '+Format('%.1f', [(T4-T3)*86400000])); Memo1.Lines.Add('Load '+Format('%.1f', [(T6-T5)*86400000])); Memo1.Lines.Add('Copy '+Format('%.1f', [(T7-T6)*86400000])); // Memo1.Lines.Add('1 '+NomTuile); end; end; end; Decal.X:= Decal.X-256; TotDecal.X:= TotDecal.X-256; end;
A : Sur mon PC (Pentium 4), total environ 120 mS :
- La partie "Decal" coûte environ 31 mS
- La partie "NomC" coûte moins d'une mS
- La partie "Load" coûte environ 16 mS (à multiplier par 5)
- La partie "Copy" coûte 4 fois sur 5 : 0ms et une fois environ 16 mS ??
B : Sur mon Raspberry Pi 3B+, total environ 300 mS:
- La partie "Decal" coûte environ 95 mS
- La partie "NomC" coûte environ 1 mS
- La partie "Load" coûte environ 35 mS (à multiplier par 5)
- La partie "Copy" coûte environ 5 mS (à multiplier par 5)
Il est évident que la partie la plus coûteuse (~ 80%) est liée au chargement("Load"), vient ensuite le décalage (~ 20%) ("Decal") des 4/5 de la surface totale du bitmap de la Carte.
Cordialement.
Pierre
Apparemment, j'ai enfin résolu mon problème de mauvais placement. Il faut toutefois que je continue mes tests.
L'erreur n'était pas "que" liée à la vitesse du déplacement, mais à deux choses :
- La première, liée à la vitesse, lorsque l'incrément de déplacement était trop grand : résolu par la première correction que j'avais faite et qui consistait à tronçonner les grands déplacements,
- L'autre, plus subtile, était liée aux déplacements en sortant d'une tuile par un des ses angles ; les critères de sélection n'étaient pas bons. Ce n'était pas facile à voir car cela n'intéressait que de tous petits espaces compris entre le coin d'une tuile et son dépassement autorisé avant de passer à une autre tuile.
Il faut toutefois que je continue mes tests. Si je finis par ne plus trouver d'erreur, je vous remontrerai les procédures modifiées.
Cordialement.
Pierre
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager