如何在Matlab图形中使用非ASCII字符(用于LaTeX文档)?

9
我想把Matlab绘制的图形包含到LaTeX中。 我通常的工作流程如下:
  1. Matlab脚本创建图形,
  2. 我在可视化图形编辑器中调整需要调整的内容,
  3. 将图形保存为.fig(以便将来修改)和.eps(用于包含在LaTeX中),
  4. 我将.eps文件转换为.pdf,
  5. 在LaTeX源代码中引用PDF文件。

简而言之:当我尝试在轴标签,图例,标题等中使用非ASCII字符时(确切地说是波兰国家字符,例如'ą','ę','ś','ć'),Matlab图形编辑器中的编码正常,并且字符正确显示。 导出为.eps后,它们全部都不对了(例如:“Głębokość”变成了“G³êbokoœæ”)。

是否存在一种正确执行此操作的方法,无论是通过调整Matlab选项还是更改我的工作流程?

注意:我发现将其导出为.png或其他非矢量格式可以正确处理字符编码,但我想避免做那件事 - 我要求找到一种“保持矢量”的方法。 直接导出为.pdf会产生与.eps相同的效果,例如,它会产生错误的结果。

PS。 Matlab是R2008a,.latex文件使用pdflatex编译,.eps文件使用来自MikTeX 2.9的epstopdf(都在Win7下)。

4个回答

8
您可以查看psfrag,当我尝试在LaTeX中使用Matlab图形时,我通常使用它。您只需在Matlab图形中放置标记,然后在之后用LaTeX文本替换这些标记。最大的好处是,这使您能够在文本和图形中拥有相同的符号。
编辑:在寻找psfrag-URL时,我找到了一个Matlab脚本来简化此过程:LaPrint

我不小心忘记了我使用的是pdflatex。你有没有什么不那么丑陋的解决方法? - triazotan
Matlab可以直接在文本字段中解释Latex。你尝试过在Matlab文本字段中放置类似于“\ 'c”的Latex结构,并将解释器设置为“latex”,而不是直接输入“ć”吗? - groovingandi
是的,我有。你提供的例子可以工作,但只适用于三个波兰口音:锐音符('),字母上的点(.)和带斜杠的L(\L)。Ogonek(即在“ą”或“ę”中找到的变音符号)由\k{}表示,并且Matlab无法正确解释它。解决此问题的一种方法是使用cedilla(\c{}),但并不完全相同,看起来有点奇怪。 - triazotan
我认为Matlab的Windows版本在LaTeX解释方面会更好,我知道Linux版本存在一些问题。如果这不起作用,那么psfrag是我唯一看到的解决方案。这并不意味着您不能再使用pdflatex来编写完整的文档,但当然创建额外的图形文档、使用latex编译它们并将输出插入主文档是很麻烦的。 - groovingandi
这次我使用了 Cedilla-Solution,因为我正在制作的文档非常紧急且太大,无法设计出(至少)半自动化的图形编译通用解决方案。尽管如此,Psfrag 对于未来的工作流程是一个很好的提示,谢谢! - triazotan

4
另一个可能的解决方案是使用matlab2tikz。它创建了一个tikz/pgfplot源文件,可以直接包含在您的latex源文件中。这意味着它使用LaTeX的字体渲染功能。您可以直接编辑生成的文件来调整标签等内容。不幸的是,它并不适用于所有MATLAB图形。

1
char(2048) will be shown by `print -depsc` as 'à ',
char(5064) as 'á',
char(28808) as 'ç',
char(37000) as 'é',
char(32904) as 'è', ...

对于 Latin1 字符集中的其他字符,请参考:

for j=0:4*64;clf;subplot(1,1,1);plot(eye(2));leg='';for i=4*(j+1)-1:-1:max(1,4*j);
str=['     ',num2str(i*64)];leg(i,:)=[str(end-4:end),':',char(64*i+(0:63))];
end;
title(leg,'interpreter','none');print('-depsc',['ascii',num2str(j),'.ps']);
end;

我正在使用pdflatex,所以psfrag不是一个选项,而pdfrack似乎有问题。


1

要导出带有非ASCII ISO-8859-1字符的Matlab图形,在Windows上没有问题,但在具有UTF-8语言环境的Linux上存在Matlab漏洞和解决方法。这里的问题涉及ISO-8859-1中没有的字符,这更加棘手。以下是我在相关问题上发布的解决方案。

如果所需字符数少于256(8位格式),并且最好使用标准编码集,则一种解决方案是:

  1. 将八进制代码转换为Unicode字符;
  2. 将文件保存到目标编码标准中(以8位格式);
  3. 添加目标编码集的编码向量。

例如,如果您想导出波兰文本,需要将文件转换为ISO-8859-2。以下是使用Python(多平台)的实现:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys,codecs
input = sys.argv[1]
fo = codecs.open(input[:-4]+'_latin2.eps','w','latin2')
with codecs.open(input,'r','string_escape') as fi:
    data = fi.readlines()
with open('ISOLatin2Encoding.ps') as fenc:
    for line in data:
        fo.write(line.decode('utf-8').replace('ISOLatin1Encoding','MyEncoding'))
        if line.startswith('%%EndPageSetup'):
            fo.write(fenc.read())
fo.close()

将文件保存为eps_lat2.py;然后运行命令python eps_lat2.py file.eps,其中file.eps是由Matlab创建的eps文件,将创建带有Latin-2编码的file_latin2.eps文件。文件ISOLatin2Encoding.ps包含编码向量

/MyEncoding
% The first 144 entries are the same as the ISO Latin-1 encoding.
ISOLatin1Encoding 0 144 getinterval aload pop
% \22x
    /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
    /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
% \24x
    /nbspace /Aogonek /breve /Lslash /currency /Lcaron /Sacute /section
    /dieresis /Scaron /Scedilla /Tcaron /Zacute /hyphen /Zcaron /Zdotaccent
    /degree /aogonek /ogonek /lslash /acute /lcaron /sacute /caron
    /cedilla /scaron /scedilla /tcaron /zacute /hungarumlaut /zcaron /zdotaccent
% \30x
    /Racute /Aacute /Acircumflex /Abreve /Adieresis /Lacute /Cacute /Ccedilla
    /Ccaron /Eacute /Eogonek /Edieresis /Ecaron /Iacute /Icircumflex /Dcaron
    /Dcroat /Nacute /Ncaron /Oacute /Ocircumflex /Ohungarumlaut /Odieresis /multiply
    /Rcaron /Uring /Uacute /Uhungarumlaut /Udieresis /Yacute /Tcedilla /germandbls
% \34x
    /racute /aacute /acircumflex /abreve /adieresis /lacute /cacute /ccedilla
    /ccaron /eacute /eogonek /edieresis /ecaron /iacute /icircumflex /dcaron
    /dcroat /nacute /ncaron /oacute /ocircumflex /ohungarumlaut /odieresis /divide
    /rcaron /uring /uacute /uhungarumlaut /udieresis /yacute /tcedilla /dotaccent
256 packedarray def

以下是在Linux上使用Bash的另一种实现:

#!/bin/bash
name=$(basename "$1" .eps)
ascii2uni -a K "$1" > /tmp/eps_uni.eps
iconv -t ISO-8859-2 /tmp/eps_uni.eps -o "$name"_latin2.eps
sed -i -e '/%EndPageSetup/ r ISOLatin2Encoding.ps' -e 's/ISOLatin1Encoding/MyEncoding/' "$name"_latin2.eps

将文件保存为eps_lat2;然后运行命令sh eps_lat2 file.eps,创建使用Latin-2编码的file_latin2.eps。

通过更改脚本中的编码向量和iconv(或codecs.open)参数,可以轻松地适应其他8位编码标准。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接