将图像添加到在 matlab 中创建的多边形表面

Adding images to the surfaces of a polygon created in matlab

我在 matlab 中使用 patch 函数创建了一个 3D 截断二十面体。我想给每张脸添加图片。

显然这不可能使用补丁,但只能使用冲浪。不幸的是,在这种情况下无法使用 surf,因为使用它创建的表面始终以正方形为底。

有什么方法可以在 Matlab 中将图像添加到 3D 多边形的边上吗?

s = 0.5;
s1 = s/3;
s2 = s * 2/3;
h =s*0.5*(sqrt(5)-1);
h1=h/3;
h2=h*2/3;
k1=h+(s-h)/3;
k2=h+(s-h)*2/3;

V1_1=-s; V2_1=0; V3_1=h1;
V1_2=-s; V2_2=0; V3_2=-h1;
V1_3=-k2; V2_3=s1; V3_3=-h2;
V1_4=-k1; V2_4=s2; V3_4=-h1;
V1_5=-k1; V2_5=s2; V3_5=h1;
V1_6=-k2; V2_6=s1; V3_6=h2;
V1_7=-k2; V2_7=-s1; V3_7=-h2;
V1_8=-k1; V2_8=-s2; V3_8=-h1;
V1_9=-k1; V2_9=-s2; V3_9=h1;
V1_10=-k2; V2_10=-s1; V3_10=h2;
V1_11=-s2; V2_11=-h1; V3_11=k1;
V1_12=-s1; V2_12=-h2; V3_12=k2;
V1_13=0; V2_13=-h1; V3_13=s;
V1_14=0; V2_14=h1; V3_14=s;
V1_15=-s1; V2_15=h2; V3_15=k2;
V1_16=-s2; V2_16=h1; V3_16=k1;
V1_17=-h1; V2_17=k1; V3_17=s2;
V1_18=-h2; V2_18=k2; V3_18=s1;
V1_19=-h2; V2_19=-k2; V3_19=s1;
V1_20=-h1; V2_20=-k1; V3_20=s2;
V1_21=s; V2_21=0; V3_21=-h1;
V1_22=s; V2_22=0; V3_22=h1;
V1_23=k2; V2_23=-s1; V3_23=h2;
V1_24=k1; V2_24=-s2; V3_24=h1;
V1_25=k1; V2_25=-s2; V3_25=-h1;
V1_26=k2; V2_26=-s1; V3_26=-h2;
V1_27=k2; V2_27=s1; V3_27=h2;
V1_28=k1; V2_28=s2; V3_28=h1;
V1_29=k1; V2_29=s2; V3_29=-h1;
V1_30=k2; V2_30=s1; V3_30=-h2;
V1_31=s2; V2_31=h1; V3_31=-k1;
V1_32=s1; V2_32=h2; V3_32=-k2;
V1_33=0; V2_33=h1; V3_33=-s;
V1_34=0; V2_34=-h1; V3_34=-s;
V1_35=s1; V2_35=-h2; V3_35=-k2;
V1_36=s2; V2_36=-h1; V3_36=-k1;
V1_37=h1; V2_37=-k1; V3_37=-s2;
V1_38=h2; V2_38=-k2; V3_38=-s1;
V1_39=h2; V2_39=k2; V3_39=-s1;
V1_40=h1; V2_40=k1; V3_40=-s2;
V1_41=-h1; V2_41=s; V3_41=0;
V1_42=h1; V2_42=s; V3_42=0;
V1_43=h2; V2_43=k2; V3_43=s1;
V1_44=h1; V2_44=k1; V3_44=s2;
V1_45=s1; V2_45=h2; V3_45=k2;
V1_46=s2; V2_46=h1; V3_46=k1;
V1_47=s1; V2_47=-h2; V3_47=k2;
V1_48=s2; V2_48=-h1; V3_48=k1;
V1_49=h1; V2_49=-k1; V3_49=s2;
V1_50=h2; V2_50=-k2; V3_50=s1;
V1_51=h1; V2_51=-s; V3_51=0;
V1_52=-h1; V2_52=-s; V3_52=0;
V1_53=-h2; V2_53=-k2; V3_53=-s1;
V1_54=-h1; V2_54=-k1; V3_54=-s2;
V1_55=-s1; V2_55=-h2; V3_55=-k2;
V1_56=-s2; V2_56=-h1; V3_56=-k1;
V1_57=-s1; V2_57=h2; V3_57=-k2;
V1_58=-s2; V2_58=h1; V3_58=-k1;
V1_59=-h1; V2_59=k1; V3_59=-s2;
V1_60=-h2; V2_60=k2; V3_60=-s1;

Vertix_Matrix =[...
    V1_1 V2_1 V3_1
    V1_2 V2_2 V3_2
    V1_3 V2_3 V3_3
    V1_4 V2_4 V3_4
    V1_5 V2_5 V3_5
    V1_6 V2_6 V3_6
    V1_7 V2_7 V3_7
    V1_8 V2_8 V3_8
    V1_9 V2_9 V3_9
    V1_10 V2_10 V3_10
    V1_11 V2_11 V3_11
    V1_12 V2_12 V3_12
    V1_13 V2_13 V3_13
    V1_14 V2_14 V3_14
    V1_15 V2_15 V3_15
    V1_16 V2_16 V3_16
    V1_17 V2_17 V3_17
    V1_18 V2_18 V3_18
    V1_19 V2_19 V3_19
    V1_20 V2_20 V3_20
    V1_21 V2_21 V3_21
    V1_22 V2_22 V3_22
    V1_23 V2_23 V3_23
    V1_24 V2_24 V3_24
    V1_25 V2_25 V3_25
    V1_26 V2_26 V3_26
    V1_27 V2_27 V3_27
    V1_28 V2_28 V3_28
    V1_29 V2_29 V3_29
    V1_30 V2_30 V3_30
    V1_31 V2_31 V3_31
    V1_32 V2_32 V3_32
    V1_33 V2_33 V3_33
    V1_34 V2_34 V3_34
    V1_35 V2_35 V3_35
    V1_36 V2_36 V3_36
    V1_37 V2_37 V3_37
    V1_38 V2_38 V3_38
    V1_39 V2_39 V3_39
    V1_40 V2_40 V3_40
    V1_41 V2_41 V3_41
    V1_42 V2_42 V3_42
    V1_43 V2_43 V3_43
    V1_44 V2_44 V3_44
    V1_45 V2_45 V3_45
    V1_46 V2_46 V3_46
    V1_47 V2_47 V3_47
    V1_48 V2_48 V3_48
    V1_49 V2_49 V3_49
    V1_50 V2_50 V3_50
    V1_51 V2_51 V3_51
    V1_52 V2_52 V3_52
    V1_53 V2_53 V3_53
    V1_54 V2_54 V3_54
    V1_55 V2_55 V3_55
    V1_56 V2_56 V3_56
    V1_57 V2_57 V3_57
    V1_58 V2_58 V3_58
    V1_59 V2_59 V3_59
    V1_60 V2_60 V3_60
    ];
figure, hold on
%--- for the 12 5-vertix faces of the polygon---%
Faces_Icosahedron5=[...
    12 13 47 49 20
    14 15 17 44 45
    48 46 27 22 23
    16 11 10 1 6
    19 52 53 8 9
    50 24 25 38 51
    18 5 4 60 41
    28 43 42 39 29
    21 30 31 36 26
    2 7 56 58 3
    40 59 57 33 32
    54 37 35 34 55
    ];
patch_info5.Vertices = Vertix_Matrix;
patch_info5.Faces=Faces_Icosahedron5;
patch_info5.FaceColor='r';
hold on, patch(patch_info5);
%--- for the 20 6-vertix faces of the polygon---%
Faces_Icosahedron6=[...
    11 12 13 14 15 16
    13 14 45 46 48 47
    47 48 23 24 50 49
    46 45 44 43 28 27
    15 16 6 5 18 17
    11 12 20 19 9 10
    44 17 18 41 42 43
    5 6 1 2 3 4 
    1 10 9 8 7 2 
    52 51 38 37 54 53
    23 22 21 26 25 24
    21 22 27 28 29 30
    42 41 60 59 40 39
    31 32 33 34 35 36
    33 34 55 56 58 57
    4 3 58 57 59 60
    20 49 50 51 52 19
    38 25 26 36 35 37
    29 39 40 32 31 30
    8 53 54 55 56 7
    ];
patch_info6.Vertices = Vertix_Matrix;
patch_info6.Faces=Faces_Icosahedron6;
patch_info6.FaceColor='g';
hold on, patch(patch_info6);

这是解决方案的开始,但有用性将取决于您要在每个表面上投影的图像类型。

我们的想法是将多边形构建为 surface 而不是 patch 的集合。虽然这不是他们的强项,但 surface 可以用来绘制 3D 平面多边形甚至 'faceted' 体积,如棱柱、十二面体、二十面体等...

由于体积构建有点繁琐,为了这个例子,我将只构建一个十二面体。它的面比你的实体少,但我选择了这个,因为它只由五边形组成,这是 Matlab surface 的棘手之处。如果将此方法应用于您的问题,您会发现六边形更容易处理。


因为坐标的顺序对于获得良好的表面很重要,所以按照您的方式构建体积(计算每个顶点然后为每个面找到正确的顺序)会太乏味。为了让我们的生活更轻松,我们只构建一个表面,基础五边形(你必须构建 2 个基础表面,1 个五边形和 1 个六边形)。

剩下的只是 复制 基础表面对象(使用 copyobj),然后将每个副本放置在 3D 中它所属的位置(平移、旋转等) ).我们还将通过构建半卷来利用对称性,然后复制并再次移动它。

我们开始:


我首先在元胞数组中加载 6 张木材纹理图像:

%% // Load textures
idxFaces = [1 2 3 4 5 6] ;
for iface = idxFaces
    imgface{iface} = imread( ['E:\ICONS\working_files\Misc\Woods\wood_texture_' num2str(iface) '.jpg'] ) ;
end

然后我定义我的五边形:

%% // Pentagon definition
% http://mathworld.wolfram.com/Pentagon.html
R = 1 ;          %// Radius of containing circle
Center=[0,0,0] ; %// center of the containing circle

c1 = R * (sqrt(5)-1)./4 ;
c2 = R * (sqrt(5)+1)./4 ;
s1 = R * (sqrt(10+2.*sqrt(5)))./4 ;
s2 = R * (sqrt(10-2.*sqrt(5)))./4 ;

xb = [-s1 -s2 ; 0 -s2 ; s1  s2] + Center(1) ;
yb = [ c1 -c2 ; R -c2 ; c1 -c2] + Center(2) ;
zb = zeros(size(xb))            + Center(3) ; 

hsb = surf( xb , yb , zb , 'CData',imgface{1},'FaceColor','texturemap','EdgeColor','none') ; %// first base pentagon surface

然后我定义了一些辅助函数,这些函数将被重新用于构建卷:

%% // define helper functions
%// Translate a graphic object by the vector v=[vx vy vz]
translate    = @(h,v) set( h, 'XData',get(h,'XData')+v(1) , 'YData',get(h,'YData')+v(2) , 'ZData',get(h,'ZData')+v(3) );
%// Retrieve the "direction" vector between two points of a graphic object
getDirection = @(h,id1,id2) [ h.XData(id1)-h.XData(id2) , h.YData(id1)-h.YData(id2) , h.ZData(id1)-h.ZData(id2)] ;
%// Retrieve the point coordinates of a graphic object
getPoint     = @(h,idp) [h.XData(idp) h.YData(idp) h.ZData(idp)] ;

最后,我很好地利用了它们,我们复制了基础五边形,直到我们有了下部体积的 6 个面:

%% // Lower volume
angleRot = 116 + 34/60 ;                %// pentagon dihedral angle  = 16°34'
dirPoints = [1 1;6 5;4 1;1 2;2 3;3 6] ; %// index of points which will be used to determinate direction and origin of the rotation

hs(1) = hsb ; %// include base surface into handle array
hax = gca ;   %// get current axis handle
for iface=2:6
    %// copy the base surface object
    hs(iface) = copyobj(hsb,hax) ;
    %// rotate it
    rotate(hs(iface), getDirection(hsb,dirPoints(iface,1), dirPoints(iface,2)) , angleRot , getPoint(hsb,dirPoints(iface,1)) )
    %// set the texture
    set( hs(iface) , 'CData',imgface{iface},'FaceColor','texturemap','EdgeColor','none') ;
end

哟吼,我们有一个半十二面体,现在我们简单地复制所有这些,最后一次翻转,平移和旋转以获得完整的体积:

%% Now copy all that, filp vertical then move up
ht = copyobj( hs,hax) ;                 %// copy the 6 surfaces in one go
rotate( ht , [0 1 0] , 180, [0 0 0])    %// flip them verticaly

%// translate then one by one
translationDistance = getPoint(hs(2),1) - getPoint(ht(2),2) ;
for iface = 1:6
    ht(iface).ZData = ht(iface).ZData + translationDistance(3) ;
end
rotate( ht , [0 0 1] , 36, [0 0 0])     %// Align the 2 sub-volumes

%% // final rendering
axis equal
axis off

这是上面代码的快速呈现:


正如我在开始时所暗示的那样,如果您的图像像 "texture" 这样,这将可以正常工作。如果要将特定图像投影到这些表面上,图像将会变形。即使是三角形、五边形或六边形也会以有趣的方式呈现图像。
只有 square 表面才能正确地对图像(始终为正方形)进行纹理处理。

另请检查此主题中的不同答案:Animate text in MATLAB 您会发现几个在表面上使用纹理贴图的示例。