Interactive/zoomable Openstreetmap without mapping toolbox
11 views (last 30 days)
Show older comments
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.
0 Comments
Accepted Answer
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!
More Answers (0)
See Also
Categories
Find more on Downloads in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!