Interactive/zoomable Openstreetmap without mapping toolbox

11 views (last 30 days)
Hi,
I created a function for a figure with an interactive high resolution Openstreetmap.
The problem is that the OSM is in grayscale and not original colored.
I think the problem is that the tiles are not loaded correctly. Maybe it is a wrong url or something like that.
Here is the function:
function interactiveWebmap(lat, lon, initialZoom)
% Initialize the figure and UI elements
fig = figure('Name', 'Interactive Webmap', 'NumberTitle', 'off', ...
'MenuBar', 'none', 'ToolBar', 'none', 'WindowButtonDownFcn', @mouseDownCallback, ...
'WindowScrollWheelFcn', @scrollWheelCallback, ...
'Position', [100, 100, 800, 600]); % Set a reasonable size for the figure
ax = axes('Parent', fig);
zoomLevel = initialZoom;
currentLat = lat;
currentLon = lon;
dragging = false;
startPos = [];
% Initial map load
updateMap(currentLat, currentLon, zoomLevel);
function scrollWheelCallback(~, event)
if event.VerticalScrollCount > 0
zoomOutCallback();
else
zoomInCallback();
end
end
function mouseDownCallback(~, ~)
% Set dragging to true and record the starting position
dragging = true;
startPos = get(fig, 'CurrentPoint');
% Set the WindowButtonMotionFcn and WindowButtonUpFcn callbacks
set(fig, 'WindowButtonMotionFcn', @mouseMoveCallback);
set(fig, 'WindowButtonUpFcn', @mouseUpCallback);
end
function mouseMoveCallback(~, ~)
% If dragging, update the map position
if dragging
currentPos = get(fig, 'CurrentPoint');
% Calculate movement delta in pixels
dx = (currentPos(1) - startPos(1)) * 0.01 / zoomLevel;
dy = (startPos(2) - currentPos(2)) * 0.01 / zoomLevel;
% Update latitude and longitude
currentLon = currentLon - dx;
currentLat = currentLat + dy;
% Update the map with new coordinates
updateMap(currentLat, currentLon, zoomLevel);
% Update start position
startPos = currentPos;
end
end
function mouseUpCallback(~, ~)
% Stop dragging
dragging = false;
set(fig, 'WindowButtonMotionFcn', '');
set(fig, 'WindowButtonUpFcn', '');
end
function zoomInCallback(~, ~)
if zoomLevel < 19
zoomLevel = zoomLevel + 1;
updateMap(currentLat, currentLon, zoomLevel);
end
end
function zoomOutCallback(~, ~)
if zoomLevel > 0
zoomLevel = zoomLevel - 1;
updateMap(currentLat, currentLon, zoomLevel);
end
end
function updateMap(lat, lon, zoom)
% Define the number of tiles to fetch for the current view
tilesPerSide = 3; % Fetch a 3x3 grid of tiles
[xtile, ytile] = latLonToTile(lat, lon, zoom);
% Preallocate the map image
mapImage = uint8(zeros(256 * tilesPerSide, 256 * tilesPerSide, 3));
% Fetch tiles and stitch them together
for x = 1:tilesPerSide
for y = 1:tilesPerSide
tileX = xtile + x - 2;
tileY = ytile + y - 2;
url = sprintf('https://tile.openstreetmap.org/%d/%d/%d.png', zoom, tileX, tileY);
try
% Fetch the tile image from the web
tileImage = imread(url);
% Ensure the tile is an RGB image
if size(tileImage, 3) == 1
tileImage = repmat(tileImage, [1, 1, 3]);
end
catch
warning('Failed to load tile: (%d, %d)', tileX, tileY);
% Use a white tile if failed to load
tileImage = 255 * ones(256, 256, 3, 'uint8');
end
% Compute the correct position for each tile in the final image
mapImage((y-1)*256+1:y*256, (x-1)*256+1:x*256, :) = tileImage;
end
end
% Display the map image
imshow(mapImage, 'Parent', ax);
title(ax, sprintf('OpenStreetMap\nLat: %.4f, Lon: %.4f, Zoom: %d', lat, lon, zoom));
end
function [xtile, ytile] = latLonToTile(lat, lon, zoom)
% Convert latitude and longitude to tile coordinates
n = 2^zoom;
xtile = floor((lon + 180) / 360 * n);
ytile = floor((1 - log(tan(deg2rad(lat)) + sec(deg2rad(lat))) / pi) / 2 * n);
end
function rad = deg2rad(deg)
% Convert degrees to radians
rad = deg * pi / 180;
end
function sec = sec(x)
% Compute the secant of x (1/cos(x))
sec = 1 ./ cos(x);
end
end
Example Berlin, Germany
interactiveWebmap(52.5200, 13.4050, 12);
Maybe you are able to help me.
Thank you.

Accepted Answer

Ganesh
Ganesh on 7 Aug 2024
Edited: Ganesh on 7 Aug 2024
You encounter this issue as the image you download from the URL is not in "RGB format" but is an "Indexed Image", which needs to be converted to an "RGB picture" using the "ColorMap" attached to the image. Have attached the following code to illustrate the same:
% The attached image has been downloaded from the URL you have mentioned
[image, colorMap] = imread('1342.png');
imshow(image)
imshow(image,colorMap)
You could possibly store the Color Map and then use it to render the whole image, but I see that you are making a tile for each of the PNGs, and hence converting it to RGB would be easier.
rgbImage = ind2rgb(image,colorMap);
imshow(rgbImage)
You can modify your code in the following way to be able to render the colored image
% Line 80
[tileImage, imgMap] = imread(url);
tileImage = ind2rgb(tileImage,imgMap)*256;
You may use the below link to learn more on the functions mentioned above:
Hope this helps!
  1 Comment
Martin Möhring
Martin Möhring on 9 Aug 2024
Hi Ganesh,
great, it works perfect.
Thank you very much for the help and the explanation.

Sign in to comment.

More Answers (0)

Categories

Find more on Downloads in Help Center and File Exchange

Products


Release

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!