• MATLAB | 绘图复刻(十三) | 带NaN图例的地图绘制


    有粉丝问我地图绘制如何添加NaN,大概像这样:

    或者这样:

    直接上干货:


    原始绘图

    假设我们有这样的一张图地图,注意运行本文代码需要去matlab官网下载Mapping Toolbox工具箱,但是其实原理都是相似的,如果M_map工具箱绘图也是类似的修改方法。

    此外此处用到的nclCM函数如何获取请看这篇文章:https://slandarer.blog.csdn.net/article/details/127935365

    或者去文末gitee仓库获取也行。

    % 需要mapping toolbox
    [Z,R]=readgeoraster('n39_w106_3arc_v2.dt1','OutputType','double');
    
    key.GTModelTypeGeoKey=2;
    key.GTRasterTypeGeoKey=2;
    key.GeographicTypeGeoKey=4326;
    
    filename='southboulder.tif';
    geotiffwrite(filename,Z,R,'GeoKeyDirectoryTag',key)
    
    usamap([39 40],[-106 -105])
    g=geoshow(filename,'DisplayType','mesh');
    
    % 190 300 363
    colormap(nclCM(15,100))
    cbHdl=colorbar();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16


    1 方法一

    1.1 添加NaN

    对于这个工具箱的这种绘图方式,比如我们想将数值低于2100的数值改成NaN,首先将原始代码改成这样:

    % 需要mapping toolbox
    [Z,R]=readgeoraster('n39_w106_3arc_v2.dt1','OutputType','double');
    
    key.GTModelTypeGeoKey=2;
    key.GTRasterTypeGeoKey=2;
    key.GeographicTypeGeoKey=4326;
    
    filename='southboulder.tif';
    % 设置NaN值
    Z(Z<2100)=nan;
    geotiffwrite(filename,Z,R,'GeoKeyDirectoryTag',key)
    
    
    usamap([39 40],[-106 -105])
    g=geoshow(filename,'DisplayType','mesh');
    
    % 190 300 363
    colormap(nclCM(15,100))
    cbHdl=colorbar();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    1.2 生成NaN图例

    在绘图区域外绘制个小方块并生成图例:

    % 绘制nan图例
    nanHdl=fill([0,1,1,0]-1000,[0,0,1,1]-1000,[240,240,240]./255,...
        'EdgeColor','none','EdgeColor',[160,160,160]./255,'LineWidth',1.2,...
        'DisplayName',' NaN');
    lgdHdl=legend(nanHdl);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.3 修改图例位置

    将上一步的代码改成这样(可能大家绘图比例不同需要根据实际情况微调):

    % 修改colorbar位置
    tPosition=cbHdl.Position;
    cbHdl.Position(1)=cbHdl.Position(1)+tPosition(3).*1.5;
    cbHdl.Position(2)=cbHdl.Position(2)+tPosition(4)./10;
    cbHdl.Position(4)=cbHdl.Position(4)-tPosition(4)./10;
    
    % 绘制nan图例
    nanHdl=fill([0,1,1,0]-1000,[0,0,1,1]-1000,[240,240,240]./255,...
        'EdgeColor','none','EdgeColor',[160,160,160]./255,'LineWidth',1.2,...
        'DisplayName',' NaN');
    lgdHdl=legend(nanHdl);
    lgdHdl.Box='off';
    lgdHdl.ItemTokenSize=[16,16];
    lgdHdl.Position(1)=tPosition(1)+tPosition(3).*1.3;
    lgdHdl.Position(2)=tPosition(2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    1.4 方法一完整代码

    % 需要mapping toolbox
    [Z,R]=readgeoraster('n39_w106_3arc_v2.dt1','OutputType','double');
    
    key.GTModelTypeGeoKey=2;
    key.GTRasterTypeGeoKey=2;
    key.GeographicTypeGeoKey=4326;
    
    filename='southboulder.tif';
    % 设置NaN值
    Z(Z<2100)=nan;
    geotiffwrite(filename,Z,R,'GeoKeyDirectoryTag',key)
    
    
    usamap([39 40],[-106 -105])
    g=geoshow(filename,'DisplayType','mesh');
    
    % 190 300 363
    colormap(nclCM(15,100))
    cbHdl=colorbar();
    % 修改colorbar位置
    tPosition=cbHdl.Position;
    cbHdl.Position(1)=cbHdl.Position(1)+tPosition(3).*1.5;
    cbHdl.Position(2)=cbHdl.Position(2)+tPosition(4)./10;
    cbHdl.Position(4)=cbHdl.Position(4)-tPosition(4)./10;
    
    % 绘制nan图例
    nanHdl=fill([0,1,1,0]-1000,[0,0,1,1]-1000,[240,240,240]./255,...
        'EdgeColor','none','EdgeColor',[160,160,160]./255,'LineWidth',1.2,...
        'DisplayName',' NaN');
    lgdHdl=legend(nanHdl);
    lgdHdl.Box='off';
    lgdHdl.ItemTokenSize=[16,16];
    lgdHdl.Position(1)=tPosition(1)+tPosition(3).*1.3;
    lgdHdl.Position(2)=tPosition(2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2 方法二

    2.1 重设范围

    这里假设NaN值被存为了-999,我们将将NaN部分数值设置为非NaN值最小值-1/10的非NaN值数值范围,这样colorbar灰色部分的长度就会是不是灰色的部分长度的1/10。

    % 需要mapping toolbox
    [Z,R]=readgeoraster('n39_w106_3arc_v2.dt1','OutputType','double');
    
    key.GTModelTypeGeoKey=2;
    key.GTRasterTypeGeoKey=2;
    key.GeographicTypeGeoKey=4326;
    
    filename='southboulder.tif';
    % 假设NaN值被存为-999
    Z(Z<2100)=-999;
    
    % 将其数值设置为非NaN值最小值-1/10的非NaN值数值范围
    % 这样colorbar灰色部分的长度就会是不是灰色的部分长度的1/10;
    Z(Z==-999)=nan;minVal=min(min(Z));
    Z(isnan(Z))=min(min(Z))-(max(max(Z))-min(min(Z)))./10;
    geotiffwrite(filename,Z,R,'GeoKeyDirectoryTag',key)
    
    usamap([39 40],[-106 -105])
    g=geoshow(filename,'DisplayType','mesh');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.2 修改配色

    往colormap前面续加上一段等长的灰色:

    CList=nclCM(15,100);
    CList=[(CList(:,1).*0+1)*[240,240,240]./255;CList];
    colormap(CList)
    cbHdl=colorbar();
    
    • 1
    • 2
    • 3
    • 4

    2.3 中心移动到NaN与数值交界处

    使用我自己写的setPivot函数:

    function setPivot(varargin)
    % @author:slandarer
    if nargin==0
        ax=gca;pivot=0;
    else
        if isa(varargin{1},'matlab.graphics.axis.Axes')
            ax=varargin{1};
            if nargin>1
                pivot=varargin{2};
            else
                pivot=0;
            end
        else
            ax=gca;pivot=varargin{1};
        end
    end
    try
        CLimit=get(ax,'CLim');
    catch
    end
    try
        CLimit=get(ax,'ColorLimits');
    catch
    end
    % CMap=get(ax,'Colormap');
    CMap=colormap(ax);
    
    CLen=[pivot-CLimit(1),CLimit(2)-pivot];
    if all(CLen>0)
        [CV,CInd]=sort(CLen);
        CRatio=round(CV(1)/CV(2).*300)./300;
        CRatioCell=split(rats(CRatio),'/');
        if length(CRatioCell)>1
            Ratio=[str2double(CRatioCell{1}),str2double(CRatioCell{2})];
            Ratio=Ratio(CInd);
            N=size(CMap,1);
            CList1=CMap(1:floor(N/2),:);
            CList2=CMap((floor(N/2)+1):end,:);
            if mod(N,2)~=0
                CList3=CList2(1,:);CList2(1,:)=[];
                CInd1=kron((1:size(CList1,1))',ones(Ratio(1)*2,1));
                CInd2=kron((1:size(CList2,1))',ones(Ratio(2)*2,1));
                CMap=[CList1(CInd1,:);repmat(CList3,[Ratio(1)+Ratio(2),1]);CList2(CInd2,:)];
            else
                CInd1=kron((1:size(CList1,1))',ones(Ratio(1),1));
                CInd2=kron((1:size(CList2,1))',ones(Ratio(2),1));
                CMap=[CList1(CInd1,:);CList2(CInd2,:)];
            end
            % set(ax,'Colormap',CMap)
            colormap(ax,CMap);
        end
    end
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    中心移动到NaN与数值交界处:

    % 调整配色范围
    setPivot(minVal)
    
    • 1
    • 2

    2.4 修改图例标签

    % 调整colorbar标签文字
    cbHdl.TickLabels{cbHdl.Ticks<minVal}='';
    cbHdl.TickLabels{1}='NaN';
    
    • 1
    • 2
    • 3

    2.5 方法二完整代码

    % 需要mapping toolbox
    [Z,R]=readgeoraster('n39_w106_3arc_v2.dt1','OutputType','double');
    
    key.GTModelTypeGeoKey=2;
    key.GTRasterTypeGeoKey=2;
    key.GeographicTypeGeoKey=4326;
    
    filename='southboulder.tif';
    % 假设NaN值被存为-999
    Z(Z<2100)=-999;
    
    % 将其数值设置为非NaN值最小值-1/10的非NaN值数值范围
    % 这样colorbar灰色部分的长度就会是不是灰色的部分长度的1/10;
    Z(Z==-999)=nan;minVal=min(min(Z));
    Z(isnan(Z))=min(min(Z))-(max(max(Z))-min(min(Z)))./10;
    geotiffwrite(filename,Z,R,'GeoKeyDirectoryTag',key)
    
    usamap([39 40],[-106 -105])
    g=geoshow(filename,'DisplayType','mesh');
    
    % 往colormap前面续加上一段等长的灰色
    CList=nclCM(15,100);
    CList=[(CList(:,1).*0+1)*[240,240,240]./255;CList];
    colormap(CList)
    cbHdl=colorbar();
    
    % 调整配色范围
    setPivot(minVal)
    
    % 调整colorbar标签文字
    cbHdl.TickLabels{cbHdl.Ticks<minVal}='';
    cbHdl.TickLabels{1}='NaN';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    以上已经是完整代码,懒得一一搜集文件可以从以下Gitee仓库获取,setPivot函数和nclCM工具包我也一块扔文件夹啦:

  • 相关阅读:
    新特性解读 | MySQL 8.0 在线调整 REDO
    goland安装教程
    路由vue-router(二)
    java-php-python-宠物医院管理系统计算机毕业设计
    【等保小知识】等保整改是什么意思?整改内容包括哪些?
    需求可追溯性的四个最佳实践
    uni-app实现拍照功能
    V831——车牌识别
    【2023,学点儿新Java-48】变量与运算符 (阶段性复习):关键字和保留,回顾:标识符的命名规则,变量的基本使用
    Stylegan3卡在Setting up PyTorch plugin “upfirdn2d_plugin“...怎么办?一招教你解决!
  • 原文地址:https://blog.csdn.net/slandarer/article/details/134543035