Matlab: Как назначить разные цветовые карты / цветовые полосы для разных поверхностей на одном и том же рисунке - PullRequest
11 голосов
/ 10 ноября 2011

Я довольно новичок в Matlab и у меня есть несколько вопросов. Я получил две поверхности и плоскость на одной фигуре. Я хочу использовать другую цветовую карту и цветовую панель для b и другую цветовую карту и цветовую панель для c. s фиксированный цвет, так что это не проблема.

Позвольте мне попытаться объяснить, чего я пытаюсь достичь:

cmap1 = colormap (topobathy) -> cmap1 в 64x3 раза больше ожидаемого

cmap2 = Colormap (redwhitegreen)

создать cdata1 с помощью cmap1 (это первая часть, которую я не могу понять, как масштабировать данные z с помощью cmap1, по умолчанию CData содержит значения z)

б = прибой (х, у, г, cdata1)

colorbar для b с использованием значений z

c = pcolor (x, y, (z-z0)) - я хочу использовать cmap2 для этого.

colorbar для c с использованием (z-z0) значений

Вот что у меня есть и проблемы, с которыми я сталкиваюсь

b=surf(x,y,z);
colormap(topobathy);
cbar1=colorbar;
set(get(cbar1,'ylabel'),'String', 'Elevation (m)', 'Rotation', 90)
hold on;
s=surf(x,y,z1,'FaceColor',[0.278 0.788 0.788])
hold on;
change=z-z0;     
c=pcolor(x,y,change)
set(c,'ZData',100 + 0*change); %plotting it above the other surfaces
colormap(redwhitegreen)`

На данный момент цветовая карта установлена ​​на красно-белый для b, цветная полоса b Я не могу получить вторую цветовую панель с собственным клиром и т. Д.

Я использовал freezeColors и cbfreeze, описанные в этой ссылке: http://blogs.mathworks.com/pick/2009/07/24/using-multiple-colormaps-in-a-single-figure/

но одно работает, а другое напутывает (наверное, по моей вине). Я хочу узнать, как получить полный контроль над моими объектами без использования внешних m-файлов.

Любая помощь приветствуется.

Ответы [ 3 ]

16 голосов
/ 10 ноября 2011

Основная идея состоит в том, что вы объединяете карты цветов, а затем сдвигаете / масштабируете данные цвета (CData) различных маркеров графика, чтобы выровнять их с нужными частями карты цветов.Таким образом, не зная, каковы ваши пользовательские функции или конкретные данные, вы можете сделать что-то вроде colormap(topobathy(64); redwhitegreen(64)) и затем масштабировать CData из b в диапазон [1,64] и CData из c вдиапазон [65,128].

На веб-сайте MathWorks есть превосходное руководство, которое объясняет все это (даже использует surf() и pcolor(), как в вашем примере):

http://www.mathworks.com/support/tech-notes/1200/1215.html#Example_1

Для цветовой шкалы вы можете просто подделать галочки и метки аналогичным образом.Вот примерный пример создания цветной полосы для приведенного выше примера:

h = colorbar;
ticks = [1 16:16:64 64:16:128];
ticks(5:6) = [62 66];
set(h, 'YTick', ticks);

labels = num2str(repmat(linspace(min(Z(:)), max(Z(:)), 5), 1, 2)', 2);
set(h, 'YTickLabel', labels)

enter image description here

1 голос
/ 20 февраля 2015

Matlab предоставил код для функции newclim, которая четко решает эту проблему путем объединения цветовых карт в одну цветовую карту. Я мог найти эту документацию только в справке 2012b, но не в сети.

Обратите внимание, что оси, используемые для обновления CLim в качестве последнего шага, могут быть осями для просмотра графиков, как я применил этот код.

Расчет пределов цвета

Ключом к этому примеру является вычисление значений для CLim, которые заставляют каждую поверхность использовать раздел цветовой карты, содержащий соответствующие цвета.

Чтобы вычислить новые значения для CLim, вам нужно знать

  • Общая длина карты цветов (CmLength)

  • Начальный слот цветовой карты для использования для каждой оси (BeginSlot)

  • Конечный слот карты цветов для использования для каждой оси (EndSlot)

  • Минимальное и максимальное значения CData графических объектов, содержащихся в осях. То есть по значениям оси CLim свойство определено MATLAB, когда CLimMode установлен автоматически (CDmin и CDmax).

Сначала определите области вспомогательных участков и нанесите на поверхность поверхности.

im1 = load('cape.mat');
im2 = load('flujet.mat');
ax1 = subplot(1,2,1); 
imagesc(im1.X) 
axis(ax1,'image')
ax2 = subplot(1,2,2);
imagesc(im2.X) 
axis(ax2,'image')

Объединение двух цветовых карт и установка новой цветовой карты.

colormap([im1.map;im2.map])

Получите данные, необходимые для расчета новых значений для CLim.

CmLength   = length(colormap);   % Colormap length
BeginSlot1 = 1;                  % Beginning slot
EndSlot1   = length(im1.map);    % Ending slot
BeginSlot2 = EndSlot1 + 1; 
EndSlot2   = CmLength;
CLim1      = get(ax1,'CLim');  % CLim values for each axis
CLim2      = get(ax2,'CLim');

Определение функции для вычисления значений CLim

Вычисление новых значений для CLim включает определение части цветовой карты, которую вы хотите использовать для каждой оси, относительно общего размера цветовой карты и соответственно масштабирование ее диапазона Clim. Вы можете определить функцию MATLAB для этого.

function CLim = newclim(BeginSlot,EndSlot,CDmin,CDmax,CmLength)
   %                Convert slot number and range
   %                to percent of colormap
   PBeginSlot    = (BeginSlot - 1) / (CmLength - 1);
   PEndSlot      = (EndSlot - 1) / (CmLength - 1);
   PCmRange      = PEndSlot - PBeginSlot;
   %                Determine range and min and max 
   %                of new CLim values
   DataRange     = CDmax - CDmin;
   ClimRange     = DataRange / PCmRange;
   NewCmin       = CDmin - (PBeginSlot * ClimRange);
   NewCmax       = CDmax + (1 - PEndSlot) * ClimRange;
   CLim          = [NewCmin,NewCmax];
end

Входные аргументы указаны в маркированном списке выше. Функция сначала вычисляет процент от общей цветовой карты, которую вы хотите использовать для определенных осей (PCmRange), а затем вычисляет диапазон CLim, необходимый для использования этой части цветовой карты, учитывая диапазон CData в осях. Наконец, он определяет минимальные и максимальные значения, необходимые для рассчитанного диапазона CLim, и возвращает эти значения. Эти значения являются цветовыми пределами для заданных осей.

Использование функции

Используйте функцию newclim, чтобы установить значения CLim для каждой оси. Заявление

set(ax1,'CLim',newclim(BeginSlot1,EndSlot1,CLim1(1),...
        CLim1(2),CmLength))

устанавливает значения CLim для первых осей, чтобы поверхность использовала цветовые интервалы от 65 до 120. Освещенная поверхность использует нижние 64 слота. Вам также необходимо сбросить значения CLim.

set(ax2,'CLim',newclim(BeginSlot2,EndSlot2,CLim2(1),...
        CLim2(2),CmLength))

Как работает функция

MATLAB позволяет указывать любые значения для свойства CLim для осей, даже если эти значения не соответствуют CData графических объектов, отображаемых на осях. Минимальное значение CLim всегда отображается на первый цвет в цветовой карте, а максимальное значение CLim всегда отображается на последний цвет в цветовой карте, независимо от того, существуют ли на самом деле какие-либо значения CData, соответствующие этим цветам. Поэтому, если вы задаете значения для CLim, которые выходят за пределы фактического минимума или максимума CData объекта, MATLAB окрашивает объект только подмножеством цветовой карты.

Функция newclim вычисляет значения для CLim, которые отображают фактические значения CData графического объекта в указанные вами начальные и конечные слоты цветовой карты. Это достигается путем определения «виртуального» графического объекта, имеющего вычисленные значения CLim.

1 голос
/ 23 июля 2014

У меня была та же проблема, что и у вас, и лучшее (и единственное) решение, которое я нашел, было следующее:

  1. Объединить обе цветовые карты, которые я хотел:

    cmap1 = jet (64); cmap2 = медь (64); color_map = [cmap1; cmap2];

    Итак, первая цветовая карта (cmap1) будет использоваться для Axes1, а вторая цветовая карта (cmap2) для Axes2. Я думаю, что Оси1 и Оси2 находятся на одном рисунке.

  2. Нормализуйте данные, задав шкалу от 0 до 1 для данных осей1 и от 1 до 2 для данных осей2. Итак, Оси1 в [0, 1] и Оси2 в [1 2].

    data1 = data1 - lower_limit1; data1 = double (data1 ./ (upper_limit1 - lower_limit1));

    Для набора данных осей 2:

    data2 = data2 - lower_limit;
    data2 = double(data2./(upper_limit2 - lower_limit2)) + 1;
    
  3. При их отображении:

    • Оси1:
    pcolor(handle_axes1, x_axis, y_axis, data1); shading(handle_axes1,'FLAT'); 
    caxis(handle_axes1, [0 2]);
    
    % Colorbar
    h_colorbar = colorbar('peer', handle_axes1);
    set(h_colorbar, 'YLim', [0 1]);
    
    labels = num2str(linspace(lower_limit1, upper_limit1, 6)', 2);
    set(h_colorbar, 'YTick', linspace(0, 1, 6));
    set(h_colorbar, 'YTickLabel', labels);
    
    • Оси2:
    pcolor(handle_axes2, x_axis, y_axis, data2); shading(handle_axes2,'FLAT'); 
    caxis(handle_axes2, [0 2]);
    
    % Colorbar
    h_colorbar2 = colorbar('peer', handle_axes2);
    set(h_colorbar2, 'YLim', [1 2]);
    
    labels = num2str(linspace(lower_limit2, upper_limit2, 6)', 2);
    set(h_colorbar2, 'YTick', linspace(1, 2, 6));
    set(h_colorbar2, 'YTickLabel', labels);
    

Используйте pcolor или surf, в зависимости от ваших потребностей. Надеюсь, это поможет!

...