构造三元网格,在 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")
产生以下内容:
我需要评估一个函数(比方说) 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")
产生以下内容: