How to keep indexed colors of patches, when switching to Face-Vertex syntax.
33 views (last 30 days)
Show older comments
John
on 2 Dec 2025 at 23:17
I'm trying to translate some code from the patch(X,Y,Z,... syntax to the patch("Faces",...,"Vertices",... syntax. I want to preserve direct mapping from the colormap. In the example code below, how should the patch call in the true branch be changed to mimic the results of the patch call in the false branch?
function patchComparison(useFaceVertex)
faces = { [0,0,0;
1.5,0,0;
1.5,1.5,0;
0,1.5,0] ;
[2,0,1;
4,0,1;
3,sqrt(3),1] ;
[1,2,2;
2,3,2;
1,4,2;
0,3,2]};
figure;
for index = 1 : size(faces,1)
ddata = faces{index};
if useFaceVertex
patch("Faces", 1:size(ddata,1), "Vertices", ddata, ...
"FaceVertexCData", index, "FaceColor", 'flat', ...
"CDataMapping", 'direct', "FaceVertexCDataMode", "manual");
else
patch(ddata(:,1), ddata(:,2), ddata(:,3), index);
end
end
end
1 Comment
Stephen23
on 3 Dec 2025 at 10:23
Edited: Stephen23
on 3 Dec 2025 at 13:40
Original colors:
faces = {...
[0,0,0; 1.5,0,0; 1.5,1.5,0; 0,1.5,0];...
[2,0,1; 4,0,1; 3,sqrt(3),1];...
[1,2,2; 2,3,2; 1,4,2; 0,3,2]};
% Left
subplot(1,2,1);
for index = 1:size(faces,1)
ddata = faces{index};
patch(ddata(:,1), ddata(:,2), ddata(:,3), index);
end
view(3)
title('Original: X, Y, Z, C');
% Right
subplot(1,2,2);
for index = 1:size(faces,1)
ddata = faces{index};
patch("Faces", 1:size(ddata,1), "Vertices", ddata, ...
"FaceVertexCData", index, "FaceColor", 'flat', ...
"CDataMapping", 'direct',...
"FaceVertexCDataMode", "manual");
end
view(3);
title('Faces & Vertices (direct)');
Note that even though they look the same color, those shapes on the right actually are different colors, corresponding to the colormap rows 1, 2, & 3 (due to the "direct" mapping). We can confirm this quite easily:
pah = gca().Children;
cmap = colormap(gca);
cmap(3:-1:1,:)
for k = 1:numel(pah)
x = pah(k).FaceVertexCData;
cmap(x,:)
end
Accepted Answer
Stephen23
on 3 Dec 2025 at 9:19
Edited: Stephen23
on 3 Dec 2025 at 9:25
Solution:
Use "scaled" in place of "direct":
patch("Faces", 1:size(ddata,1), "Vertices", ddata, ...
"FaceVertexCData", index, ...
"FaceColor", 'flat', ...
"CDataMapping", 'scaled', ... <--------- this here !
"FaceVertexCDataMode", "manual");
Explanation
When translating from patch(X,Y,Z,C) to patch('Faces',F,'Vertices',V) with scalar color values, the key is understanding how MATLAB interprets color data differently in each case.
The original code was
patch(ddata(:,1), ddata(:,2), ddata(:,3), index);
By default this uses CDataMapping set to 'scaled', which means the color values are scaled to span the colormap based on the axes color limits (CLim). When you have values 1, 2, and 3 across multiple patches, MATLAB automatically scales these to map to different colors across the colormap.
The correct translation is:
patch("Faces", 1:size(ddata,1), "Vertices", ddata, ...
"FaceVertexCData", index, ...
"FaceColor", 'flat', ...
"CDataMapping", 'scaled', ... <--------- this here !
"FaceVertexCDataMode", "manual");
The critical points are:
- Use FaceVertexCData with a scalar value (index) to specify one color per patch face
- Set FaceColor to 'flat' for uniform face coloring
- Set CDataMapping to 'scaled' (not 'direct') to match the default behavior of patch(X,Y,Z,C)
- Set FaceVertexCDataMode to 'manual' to prevent automatic color assignment via SeriesIndex. Because we already set FaceVertexCData this should change automatically, but it does not hurt the code clarity to set it explicitly.
If you mistakenly set CDataMapping to 'direct' then the values 1, 2, 3 are interpreted as direct indices into the colormap. Since the first few entries in most colormaps (like parula) are very similar colors, all patches appear nearly the same color. With 'scaled' mapping, MATLAB scales the range of values (1 to 3) to span a wider portion of the colormap, producing visually distinct colors.
3 Comments
Stephen23
on 3 Dec 2025 at 17:01
Edited: Stephen23
on 3 Dec 2025 at 19:52
"When does scaling happen?"
humm... I don't really know what kind of magic is going on here. I guess that "scaled" is always subject to change, depending on any future data. You could try your example loop with PAUSE and DRAWNOW to see when the change actually occur.
"If an additional call to patch is made with a larger value for C than all previous calls, I would assume the colors of all patches would change?"
I guess so, as that is effectively all your loop is doing. If you want exact control over the colors you could build an appropriate colormap (e.g. with exactly three colors for your example) and use "direct".
More Answers (0)
See Also
Categories
Find more on Color and Styling 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!
