构造三元网格,在 Matlab 中评估网格和等高线图上的函数

Construct ternary grid, evaluate a function on the grid and contour plot in Matlab

我需要评估一个函数(比方说) Fxy = 2*x.^2 +3 *y.^2; 在三元网格 x 范围 (0 - 1)、y 范围 (0-1) 和 1-x-y (0 - 1) 上。 我无法构建我需要评估上述功能的三元网格。此外,一旦评估,我需要在三元等高线图中绘制函数。理想情况下,我需要轴在 (x -> y--> (1-x-y)) 的意义上逆时针旋转。

我试过

的功能
function tg = triangle_grid ( n, t )

  ng = ( ( n + 1 ) * ( n + 2 ) ) / 2;
  tg = zeros ( 2, ng );

  p = 0;

  for i = 0 : n
    for j = 0 : n - i
      k = n - i - j;
      p = p + 1;
      tg(1:2,p) = ( i * t(1:2,1) + j * t(1:2,2) + k * t(1:2,3) ) / n;
    end
  end

  return
end

为三角形边坐标之间的子区间数

n = 10 (say)

等边三角形的边坐标

t = tcoord = [0.0, 0.5,           1.0;
              0.0, 1.0*sqrt(3)/2, 0.0];

这生成了一个 x 轴为 0-1 但其他两个不是 0-1 的三角形网格。

我需要这样的东西:

... 轴范围为 0-1(0-100 也可以)。

此外,我需要知道三角网格内所有交点的坐标点。一旦我有了这个,我就可以继续评估这个网格中的函数。

我的最终目标是得到这样的东西。这更好地表示了我需要实现的目标(与我现在删除的之前的情节相比)

请注意,这两个三元图具有大小不同的等值等值线。在我的例子中,差异是一个数量级,两个非常不同的 Fxy。

如果我可以将两个三元图绘制在彼此之上,然后评估三元平面上两个等值等值线相交处的成分。构图应该是从三元图中读取的,而不是从定义三角形的矩形网格中读取的。 目前存在问题(如评论部分中突出显示的那样,一旦问题接近解决方案就会更新)。

我玩了一下文件交换提交https://www.mathworks.com/matlabcentral/fileexchange/2299-alchemyst-ternplot

如果你这样做:

[x,y]=meshgrid(0:0.1:1);
Fxy = 2*x.^2 +3 *y.^2;
ternpcolor(x(:),y(:),Fxy(:))

你得到:

三轴完全按照您在 ternpcolor 函数中所说的 (1-x-y) 创建。 "tune" 这里有很多内容,但我希望这些足以让您入门。

我是ternplot. As you have correctly surmised, ternpcolor does not do what you want, as it is built to grid data automatically. In retrospect, this was not a particularly wise decision, I've made a note的作者要修改设计。同时这段代码应该做你想做的事:

编辑:我更改了代码以查找两条曲线的交点,而不仅仅是一条。

N = 10;
x = linspace(0, 1, N);
y = x;

% The grid intersections on your diagram are actually rectangularly arranged,
% so meshgrid will build the intersections for us
[xx, yy] = meshgrid(x, y);
zz = 1 - (xx + yy);

% now that we've got the intersections, we can evaluate the function
f1 = @(x, y) 2*x.^2 + 3*y.^2 + 0.1;
Fxy1 = f1(xx, yy);
Fxy1(xx + yy > 1) = nan;

f2 = @(x, y) 3*x.^2 + 2*y.^2;
Fxy2 = f2(xx, yy);
Fxy2(xx + yy > 1) = nan;

f3 = @(x, y) (3*x.^2 + 2*y.^2) * 1000; % different order of magnitude
Fxy3 = f3(xx, yy);
Fxy3(xx + yy > 1) = nan;

subplot(1, 2, 1)
% This constructs the ternary axes
ternaxes(5);

% These are the coordinates of the compositions mapped to plot coordinates
[xg, yg] = terncoords(xx, yy);
% simpletri constructs the correct triangles
tri = simpletri(N);

hold on
% and now we can plot
trisurf(tri, xg, yg, Fxy1);
trisurf(tri, xg, yg, Fxy2);
hold off
view([137.5, 30]);

subplot(1, 2, 2);
ternaxes(5)
% Here we plot the line of intersection of the two functions
contour(xg, yg, Fxy1 - Fxy2, [0 0], 'r')
axis equal

编辑 2:如果您想找到两个等高线之间的交点,您实际上是在求解两个联立方程。这段额外的代码将为您解决这个问题(注意我现在也在上面的代码中使用了一些匿名函数):

f1level = 1;
f3level = 1000;
intersection = fsolve(@(v) [f1(v(1), v(2)) - f1level; f3(v(1), v(2)) - f3level], [0.5, 0.4]);
% if you don't have the optimization toolbox, this command works almost as well
intersection = fminsearch(@(v) sum([f1(v(1), v(2)) - f1level; f3(v(1), v(2)) - f3level].^2), [0.5, 0.4]);

ternaxes(5)
hold on
contour(xg, yg, Fxy1, [f1level f1level]);
contour(xg, yg, Fxy3, [f3level f3level]);
ternplot(intersection(1), intersection(2), 1 - sum(intersection), 'r.');
hold off

这是一个使用 R 和我的包 ggtern 的解决方案。出于比较的目的,我还在下面包含了附近的点。

library(ggtern)

Fxy      = function(x,y){ 2*x^2 + 3*y^2 }
x = y    = seq(0,1,length.out = 100)
df       = expand.grid(x=x,y=y); 
df$z     = 1 - df$x - df$y
df       = subset(df,z >= 0)
df$value = Fxy(df$x,df$y)

#The Intended Breaks
breaks = pretty(df$value,n=10)

#Create subset of the data, within close proximity to the breaks
df.sub = ldply(breaks,function(b,proximity = 0.02){
  s = b - abs(proximity)/2; f = b + abs(proximity)/2
  subset(df,value >= s & value <= f)
})

#Plot the ternary diagram
ggtern(df,aes(x,y,z)) + 
  theme_bw() + 
  geom_point(data=df.sub,alpha=0.5,color='red',shape=21) + 
  geom_interpolate_tern(aes(value = value,color=..level..), size = 1, n = 200,
                        breaks    = c(breaks,max(df$value) - 0.01,min(df$value) + 0.01),
                        base      = 'identity',
                        formula   = value ~ poly(x,y,degree=2)) +
  labs(title = "Contour Plot on Modelled Surface", x = "Left",y="Top",z="Right")

产生以下内容: