Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Servers (https://www.clubdelphi.com/foros/forumdisplay.php?f=9)
-   -   Slippy map - Visualizar mozaicos de OpenStreetMap en TDrawGrid (https://www.clubdelphi.com/foros/showthread.php?t=93978)

acprincipi 04-06-2019 01:45:01

Slippy map - Visualizar mozaicos de OpenStreetMap en TDrawGrid
 
Trabajo con Delphi7, en un pequeño server visualizador de Mapas, basado en la técnica Slippy Map de OSM. He conseguido cargar en un TDrawGrid los bmps que conforman el mapa. Cada celda del TDrawGrid aloja un bmp (de 256x256 pixel) que forma parte del mapa que estamos mostrando. Dependiendo del nivel de zoom seleccionado tendremos una grilla (o matriz) de menor o mayor tamaño.
PROBLEMA: el método drawCell va levantando la imagen (bmp) correspondiente a la celda que esta dibujando y la coloca en esa posición. Muestra el mapa correctamente hasta que movemos cualquiera de los scrollbar (Horizontal o Vertical) para navegar el mapa. En ese momento no se refresca o repinta la imagen que corresponde a cada celda. Muestra las celdas vacías. Por ejemplo si me muevo a la derecha lo que estaba pintado se va moviendo bien pero las nuevas celdas que van apareciendo no muestran nada.

Les dejo el codigo del metodo OnDrawCell:

Código Delphi [-]
procedure TfrmOSMSlippyMap.dgMAPDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  bmp: TBitmap;
  zoom_Level_dir, x, y, TileX_Pos, TileY_Pos: Integer;
begin
  bmp := TBitmap.Create();

  Try
    TileX_Pos := ACol * 256;//Cada tile mide 256 pixel de ancho, por eso al multiplicar por 256 avanzo hasta la posicion TileX_Pos donde colocarla.
    TileY_Pos := ARow * 256;//Cada tile mide 256 pixel de alto,  por eso al multiplicar por 256 avanzo hasta la posicion TileY_Pos donde colocarla.
    x := ACol;
    y := ARow;
    //Cargo del directorio de bmps la imagen correspondiente a la celda que se esta dibujando actualmente.
    //Los directorios que almacenan las imagenes que forman cada mapa (segun el nivel de zoom) cumplen con 
    // las especificaiones de OpenStreetMap (Slippy MAP - [wiki.openstreetmap.org/wiki/Slippy_map_tilenames])
    bmp.LoadFromFile(ExtractFilePath(Application.ExeName)+'Datos\'+inttostr(cbZoomLevel.ItemIndex)+'\'+i  nttostr(x)+'\'+inttostr(y)+'.bmp');

    dgMAP.Canvas.Draw(TileX_Pos ,TileY_Pos , bmp);
  finally
    bmp.Free;
  end;
end;

No pude subir el proyectito en delphi7 (de 235 kb) porque superaba la cuota otorgada, pero si alguien esta interesado en el tema me avisa y se lo paso. Son muy pocas lineas de código y viene con los bmp incluidos.
Si hay algún componente que puedan sugerirme para D6 o D7 se los agradecería mucho.
Saludos.

Saludos y gracias

acprincipi 04-06-2019 05:14:47

Administrar open street map offline
 
Olvide mencionar que la finalidad es hacer un servidor de mapas OFFLINE utilizando la técnica slippy map y los tiles o mosaicos que pueden descargarse de los sitios de open street maps, Nokia, Google maps entre otros.

WHILENOTEOF 04-06-2019 10:10:55

Yo creo que no es necesario que calcules las posición donde dibujar el bitmap en el canvas del grid (TileX_Pos y TileY_Pos), porque con el scroll esa posición para una celda determinada cambiará a nivel global, utiliza el parámetro del dibujado de la celda Rect:

Código Delphi [-]
 dgMAP.Canvas.Draw(Rect.X,Rect.Y,bmp);

WHILENOTEOF 04-06-2019 10:58:09

(Corrijo mensaje anterior que no me deja editarlo, es Left y Top de Rect). Yo creo que no es necesario que calcules las posición donde dibujar el bitmap en el canvas del grid (TileX_Pos y TileY_Pos), porque con el scroll esa posición para una celda determinada cambiará a nivel global, utiliza el parámetro del dibujado de la celda Rect:

Código Delphi [-]
 dgMAP.Canvas.Draw(Rect.Left,Rect.Y.Top,bmp);

acprincipi 04-06-2019 17:22:00

Muchas gracias WHILENOTEOF quedo solucionado.
Siguiendo con el tema de slippy map:

Quería consultar si es necesario liberar la memoria asignada cada vez que pintamos un bmp y al desplazarnos con el scroll éste queda fuera del área de visión:

Código Delphi [-]
procedure TfrmOSMSlippyMap.dgMAPDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  bmp: TBitmap;
begin
  bmp := TBitmap.Create();

  Try
    //Cargo del directorio de bmps la imagen correspondiente a la celda que se esta dibujando actualmente.
    //Los directorios que almacenan las imágenes que forman cada mapa (según el nivel de zoom) cumplen con las especificaciones de OpenStreetMap (Slippy MAP - wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
    bmp.LoadFromFile(ExtractFilePath(Application.ExeName)+'Datos\'+inttostr(cbZoomLevel.ItemIndex)+'\'+i  nttostr(ACol)+'\'+inttostr(ARow)+'.bmp');

    dgMAP.Canvas.Draw(Rect.Left ,Rect.Top , bmp);
  finally
    bmp.Free;//<-- ¿Esto libera la memoria asignada al bmp cada vez que el mismo queda fuera de la porción de la grilla que estamos visualizando?
  end;
end;

Considerando que para un mapa de nivel de zoom 9 tendremos una grilla constituida de (512x512) celdas [ (2^9)x(2^9) ], es decir un total de 262144 bmps.

¿Cual sería la mejor manera de administrar los bmp que se cargaron en una celda que ya no esta visible por habernos desplazado a otro lugar de la grilla o mapa?

WHILENOTEOF 04-06-2019 17:55:32

Yo creo que para hacer eso es que te calcules cuantos bmp te caben en la pantalla donde lo estés visualizando, y crees una lista de bitmaps con esa cantidad. Primero capturas los movimientos de scroll para saber en que posición estás respecto al mapa global de bitmaps (obviamente no se pueden cargar todos), cargas en la lista los que no tengas y liberas los que ya no te hacen falta, puede que haya varios que no necesites volver a cargar, simplemente que su posición cambia. Lo que pasa que ahí tendrás que prevenir varias cosas como que se ponga a pintar con el draw cell uno que no hayas cargado todavía, por lo tanto primero chequear que ya lo tengas cargado, y si no pintas en blanco y en cuanto esté lo dibujo. Imagino que para esto habría que crear unos threads que te hicieran el proceso de cargas y liberar bitmaps.

acprincipi 04-06-2019 19:00:09

Excelente razonamiento WHILENOTEOF. Veré como lo implemento. Por ahora estoy haciendo algunas pruebas, pero en algún momento tendré que ponerme con ese tema. Nuevamente gracias por el aporte. He conseguido mostrar hasta 4 niveles de zoom si problemas. Ahora estoy viendo como referenciar/ubicar coordenadas de Latitud y Longitud en el Mapa/Grilla.


La franja horaria es GMT +2. Ahora son las 06:34:50.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi