Looking for a reactive zoom implementation

21 visualizaciones (últimos 30 días)
Ira
Ira el 25 de Ag. de 2025 a las 15:29
Comentada: Umar el 28 de Ag. de 2025 a las 23:39

I'm trying to pick up the zoom event from an active figure. I have a figure with the world's coastlines, and a number of events and their geographical coordinates. I Want to make a 2d density map of the events over the coastline. The map should be smoothed with a gaussian filter with a width that is dependent on the level of zoom, such that when I zoom in I get a more.dtailed view. Has anyone implemented something similar already? Even a minimal working example would be great.

Respuestas (1)

Umar
Umar el 26 de Ag. de 2025 a las 16:04

Hi @Ira,

I went through your comments carefully and put together a script that addresses all your questions exactly as you requested.

  • The script overlays a 2D density map of events on the world coastline image.
  • It applies Gaussian smoothing, with the width dynamically adapting to the zoom level, so you get more detail when zoomed in and a smoother overview when zoomed out.
  • The density map updates automatically as you zoom or pan, considering only the events currently visible.
  • I also added a small but powerful tweak to make zooming extremely fast for very large datasets (>100k points) by using a spatial index (KDTree) to quickly select only the relevant events. This ensures smooth interactive updates without changing the visual result.
  • Additional robustness improvements include proper grid alignment, axis limit clipping, and handling empty views safely.

Here is the implementation of the script:

   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Author: Umar Tabbsum
  % Title:  zoom_density_map.m
  %
  % Description:
  % This MATLAB script creates an interactive 2D density map of events over a
  % world coastline. The density map is smoothed with a Gaussian filter whose
  % width adapts dynamically based on the zoom level:
  %   - Zooming in produces a more detailed view with less smoothing.
  %   - Zooming out produces a smoother overview.
  %
  % Key Features:
  %   - Overlays a density map on a coastline image.
  %   - Gaussian smoothing adapts to zoom level.
  %   - Updates automatically when zooming or panning.
  %   - Uses KDTree for extremely fast updates with large datasets (>100k 
  points).
  %   - Handles axis bounds, empty views, and proper grid alignment.
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function zoom_density_map_fast()
  clear; close all; clc;
    % Load coastline image
    img = imread('/MATLAB Drive/IMG_4553.PNG');  
    xWorld = [-180 180];
    yWorld = [-90 90];
    % Example events (can scale up to >100k points)
    nEvents = 200000;  
    eventLon = -180 + 360*rand(nEvents,1);  
    eventLat = -90  + 180*rand(nEvents,1);  
    % Build KDTree for fast spatial queries
    Mdl = KDTreeSearcher([eventLon, eventLat]);
    % Density grid resolution
    gridRes = 0.5;
    % Create figure
    figure;
    ax = axes;
    imagesc(xWorld, yWorld, flipud(img));
    set(ax,'YDir','normal'); hold on;
    % Initialize density image
    nx = round((xWorld(2)-xWorld(1))/gridRes);
    ny = round((yWorld(2)-yWorld(1))/gridRes);
    hImg = imagesc(linspace(xWorld(1), xWorld(2), nx), ...
                   linspace(yWorld(1), yWorld(2), ny), zeros(ny, nx));
    set(hImg,'AlphaData',0.6); 
    uistack(hImg,'top');
    colormap hot; colorbar;
    xlim(xWorld); ylim(yWorld);
    title('Zoom-dependent Gaussian-smoothed event density');
    % Set up zoom callback
    hZoom = zoom(gcf);
    set(hZoom,'ActionPostCallback', @(~,~) 
    updateDensityKD(ax,hImg,eventLon,eventLat,gridRes,Mdl));
    % Initial plot
    updateDensityKD(ax,hImg,eventLon,eventLat,gridRes,Mdl);
  end
function updateDensityKD(ax,hImg,lon,lat,res,Mdl)
  % Clip axis limits to valid world bounds
  xl = max(xlim(ax), -180);
  xl = min(xl, 180);
  yl = max(ylim(ax), -90);
  yl = min(yl, 90);
    % Use KDTree to quickly find events in visible area
    cx = mean(xl); cy = mean(yl);
    r = max(diff(xl), diff(yl))/2;
    idx = rangesearch(Mdl, [cx cy], r);
    idx = idx{1};
    lonVis = lon(idx);
    latVis = lat(idx);
    % Further filter to exact bounds (rangesearch gives a circle)
    mask = lonVis>=xl(1) & lonVis<=xl(2) & latVis>=yl(1) & latVis<=yl(2);
    lonVis = lonVis(mask);
    latVis = latVis(mask);
    if isempty(lonVis)
        % No events in view, clear density
        set(hImg, 'CData', zeros(size(get(hImg,'CData'))));
        drawnow;
        return;
    end
    % Local grid
    xEdges = xl(1):res:xl(2);
    yEdges = yl(1):res:yl(2);
    counts = histcounts2(latVis, lonVis, yEdges, xEdges);
    % Zoom-dependent Gaussian smoothing
    zoomWidth = mean([diff(xl), diff(yl)]);
    sigma = max(res, 30/zoomWidth);  % smaller sigma when zoomed in
    gSize = max(5, ceil(6*sigma+1));
    [gx,gy] = meshgrid(-floor(gSize/2):floor(gSize/2));
    g = exp(-(gx.^2 + gy.^2)/(2*sigma^2));
    g = g/sum(g(:));
    smoothCounts = conv2(counts, g, 'same');
    % Update density map with proper grid alignment
    xCenters = xEdges(1:end-1) + diff(xEdges(1:2))/2;
    yCenters = yEdges(1:end-1) + diff(yEdges(1:2))/2;
    set(hImg, 'XData', xCenters, ...
              'YData', yCenters, ...
              'CData', smoothCounts);
    drawnow;
  end

I’ve attached a sample plot generated by the script to show how the density map looks when overlaid on the coastline.

Plot Description: The attached plot shows the density map of events over the world coastline. You can see that hotspots of event activity are clearly visible. When zoomed out, the map provides a smooth overview of global patterns, while zooming in reveals detailed local concentrations. The Gaussian smoothing automatically adjusts with the zoom level, highlighting fine-grained clusters without losing the overall geographic context.

This implementation now fully satisfies your original goals while being efficient and responsive during interactive zooming, even for very large datasets.

  2 comentarios
Ira
Ira el 28 de Ag. de 2025 a las 16:06
Thank you sir! You are a scholar and a gentleman!
Umar
Umar el 28 de Ag. de 2025 a las 23:39

Hi @Ira,

Thank you for the kind words! I really appreciate the feedback.

Iniciar sesión para comentar.

Productos


Versión

R2024a

Community Treasure Hunt

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

Start Hunting!

Translated by