Interactive/zoomable Openstreetmap without mapping toolbox
조회 수: 7 (최근 30일)
이전 댓글 표시
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
채택된 답변
Ganesh
2024년 8월 7일
편집: Ganesh
2024년 8월 7일
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!
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 Downloads에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!