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

时间:2015-07-28 13:15:36

标签: matlab contour ternary ternplot

我需要评估一个函数(比方说) 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。

我需要这样的东西:

wiki link

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

另外,我需要知道三角形网格内所有交叉点的坐标点。有了这个,我就可以继续评估这个网格中的功能了。

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

better representation

请注意,两个三元图具有等值不同的等值线。在我的情况下,差异是一个数量级,两个非常不同的Fxy。

如果我可以将两个三元图绘制在彼此之上,然后评估三元平面上两个等值线轮廓交叉处的成分。组成应该从三元图中读取,而不是定义三角形的矩形网格。 目前存在一些问题(如评论部分中所强调的,一旦问题更接近解决方案,将更新此问题)。

3 个答案:

答案 0 :(得分:2)

I have played a bit with the file exchange submission https://www.mathworks.com/matlabcentral/fileexchange/2299-alchemyst-ternplot.

if you just do this:

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

You get:

enter image description here

The thirds axis is created exactly as you say (1-x-y) inside the ternpcolor function. There are lots of things to "tune" here but I hope it is enough to get you started.

答案 1 :(得分:2)

我是ternplot的作者。正如您所推测的那样,ternpcolor并不能满足您的需求,因为它是自动构建的网格数据。回想起来,这不是一个特别明智的决定,我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

enter image description here

编辑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

enter image description here

答案 2 :(得分:0)

以下是使用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")

产生以下内容:

example