2024年5月7日发(作者:)

维普资讯

第29卷第2期 物探化探计算技术 2007年3月 

文章编号:1001—1749(2007)O2—0171—06 

GOCAD矢量汉字数据库的开发 

朱焱辉 ,朱培民2,张英德2 

(1.中海油深圳分公司技术部,广州510240; 

2.中国地质大学地球物理与空间信息学院,湖北武汉430074) 

摘要:为了在地质建模软件GOCAD中实现常用汉字和字符的输入和显示,这里详细阐述了 

基于CoreDraw中用VBA编程提取常用汉字轮廓线坐标数据的基本方法,并形成所有汉字矢量 

字体表示的数据库。通过GOCAD进行二次开发并在该环境输出矢量汉字。同时还为输入汉字 

设计了汉字输入模块,为提取汉字提供了便利条件。实践证明,该方法方便、快捷、实用。 

关键词:汉字;GOCAD;CoreDraw;VBA 

中图分类号:TP 391.12 文献标识码:A 

0前言 

1 GOCAD汉字库建立和汉字输入 

方案 

GOCAD是由法国Nancy大学研制的地质建模 

软件。由于该软件在构造和表达三维对象上具有 

开发一个汉字字符的矢量字库并实现汉字字 

较强的能力,所以常用于地质分界面、地层、断层、 

符在GOCAD中的输入和显示软件,需要分四步完 

钻井、物化探数据等地质对象的建模和显示上,并 

成(见图1):①找出包含所有的第一级、第二级汉 

提供了相应的地质分析和解释功能。它是一个在 

字中的常用部分,以及英文、数字和标点符号共 

地质建模和地质解释中应用相当广泛的软件¨】。 

6 851个,将它们存入同一个字符文件中;②利用 

CA)CAD软件是英文版,不支持汉字的输入和显示, 

CoreDraw软件的二次开发功能,将字符文件中的 

即使是GOCAD的工程文件和文件的路径中也不 

全部字符转换成实际的字体坐标数据输出;③建立 

能含有中文字符,这给实际工作带来了诸多不便。 

矢量汉字字符数据库,将步骤②中转换输出的字符 

在进行地质建模时,难免会遇到需要显示和输入汉 

字体数据存入这个数据库中,形成一个可随时调用 

字的地方,例如地质体的名称、地理位置、区域名称 

的矢量字库;④利用GOCAD的二次开发功能,使 

等都需要进行中文输入和显示。为了解决GOCAD 

得开发出的程序能根据用户输入的汉字和字符,从 

不能输入和显示汉字的缺陷,需要构造一个实用的 

数据库中将对应字符的字体坐标数据取出,然后转 

矢量汉字库,并可以任意地进行缩放、平移、旋转等 

化成GOCAD的闭合曲线对象,并在GOCAD中显 

变换,形成完全的三维汉字。为此,作者在本文中 

示出来。 

利用CoralDraw绘图软件的字符到曲线的转换功 

能,形成GOCAD可以接受的曲线字体对象,解决 

了GOCAD汉字输入和显示的问题。在本文中,作 

者详细阐述了这种解决方案,通过实践证明,该方 

图1程序实现框图 

案方便、快捷、实用。 

Fig.1 Flow chart of program 

收稿日期:2005—11—08 

维普资讯

172 物探化探计算技术 29卷 

2矢量汉字的提取 

CoreDraw是一个优秀的通用绘图软件,它能 

将汉字或者字符转换成由汉字或字符轮廓曲线构 

成的闭合曲线图形。这种曲线形式的图形与GO— 

CAD的曲线图形对象有类似的表示方式,如果把 

汉字字符当作曲线对象对待,则可完美地显示到软 

件GOCAD中,并且可以任意地进行缩放、平移、旋 

转等变换,形成完全的三维汉字。 

为了利用CoreDraw提取矢量汉字,作者先将 

第一级和第二级常用的6 725个汉字和126个常 

用字符(包括英文26个大小写字母,0到9的lO 

个数字以及常用的标点和其它符号)代码存人到 

文件中;然后把每一个汉字或字符的轮廓曲线的控 

制点,全部转换成相对坐标数据,具体过程如下: 

(1)在CoreDraw中将汉字和字符转换成闭合 

曲线的组合。 

(2)将曲线组合图形拆分成单个的闭合曲线 

对象。 

(3)通过对闭合曲线对象中弯曲的部分进行 

插值,然后获得所有曲线对象中的控制点坐标再按 

顺序输入到文件,从而实现字符的矢量化。 

下面是程序的主要VBA实现代码。 

Dim S As Shape ’定义S为图形对象 

Dim simplecurve As Curve’定义simple— 

curve为曲线对象,创建并显示汉 

字,在此以汉字”我”为例 

ActiveLayer.CreateArtisticText 0,0,”我”,一 

cdrSimpliifedChinese,,”隶书”,100,cdr- 

Truc,c ̄Tme,,edrLeftAlignment 

ActiveLayer.Shapes(1).ConvertToCurves 

’将汉字转化成闭合曲线的组合 

ActiveLayer.Shapes(1).BreakApart 

’将闭合曲线组合拆分成不同的部分 

shapecount=ActiveLayer.Shapes.Count 

’获得当前图层中图形(闭合曲线)的数目 

’以下代码在闭合曲线的弯曲部分插人 

节点,提高字符的显示分辨率 

For ii=l To shapecount 

dotcount=l 

Set S=ActiveLayer.Shapes(ii) 

’依次获得图层中的闭合曲线对象 

Set simplecurve=S.Curve 

scgt ̄ntcount=sir ̄lecurve.Scgr ̄.Count 

’得到闭合曲线对象包含段的数目 

For iii=l To scgmenteount 

eSt scg simplecurve.Segments(dotcount) 

’依次得到闭合曲线的每一段 

If seg.Type=cdrCurveSegment Then 

’判断每一段的曲线类型,如果是 

曲线则进入下面的插值程序。 

seg.AddNodeAt(O.167) 

simplccurve.Segments(dotcount+1). 

AddNodeAt(O.2) 

simplecurve.Segments(dotcount+2). 

AddNodeAt(O.25) 

simplecurve.Segments(dotcount+3). 

AddNodeAt(0.33) 

simplecurve.Segments(doteount+4). 

AddNodeAt(0.5) 

dotcount=doteount+6 

Else 

dotcount=dotcount+l 

End If 

Next iii 

Next ii 

’为闭合曲线的弯曲部分插人节点的代码结 

束 

shapecount=ActiveLayer.Shapes.Count 

’第二次得到图形的数目 

a.writeline(”我”)’输出汉字 

a.writeline(CStr(shapecount)) 

For j=l To shapecount 

eSt S=ActiveLayer.Shapes(j) 

a.writeline(CS虹(S.Curve.Nodes.Count)) 

For i=l TO S.Curve.Nodes.Count 

x=S.Curve.Nodes(i).PositionX 

Y=S.Curve.Nodes(i).PositionY 

a.writeline(CStr(x)+””+CStr(y)) 

Next i 

Nextj 

ActiveLayer.Shapes.Al1.Dclctc 

上面的程序代码①先将S定义为Shape类型 

的对象,simplecurve定义为Curve类型的对象;② 

然后通过函数CreateArtisticText在当前图层中显示 

汉字“我”。汉字是简体中文隶书,字体尺寸为100; 

③由于此时图层中只有一个图形,即只有一个 

Shape对象,因此可通过获得这个Shape对象,调用 

函数ConvertToCurves,并将汉字转换成由曲线组合 

的图形;④通过BreakApart将曲线组合图形拆分成 

维普资讯

2期 朱焱辉等:GOCAD矢量汉字数据库的开发 173 

单个的闭合曲线对象。 

I委一 雹_嗣警蠼 墨呲 矗墙●■■E 

每个闭合曲线对象由多个节(Segment)组成。 

为了对单个闭合曲线中弯曲的节进行插值,需要调 

垂0 啊 7 

用Shape的属性Count,以获得当前图层中闭合曲 

2 1 阿 4 

线对象的数目。程序中间部分是对弯曲的节插值 

mi 3 2 吖 5 

4 3 嗄 7 

的部分,插值的方法是通过在一节中均匀地插入五 

5 4 腌 9 

个节点后实现的。程序的最后一部分是获得所有 

节点的( ,y)坐标,并将它们输入到文件,最后调 

用Delete方法,删除当前图层中所有的图形对象。 

鬻 6T89 56T8 哎锕埃挨 463 

以上是将单个的汉字转化成闭合曲线图形的 

程序。通过循环的方法就可以将外部字符文件中 

图2汉字基本资料表 

的所有字符,全部转换成由节点坐标控制的闭合曲 

Fig.2 The table of Chinese word data 

线对象。 

匮蛋 ■ ii●目■;;■●1.睡嗡苗■ 蛙●■■_E一 

隧 目目目g目目 目9 ggg目& 硝 gg目目目目g目舞●g目目 目躐 器疆圜藁摹蘸囊—曩曩嚣墨酲曩霪謇鏊 

3 矢量汉字数据库的设计与建立 

蜀 50 0 

26 0 1 

27 0 2 

为了存储汉字坐标数据,并方便数据地导出, 

需要建立适当的数据库,以存储和管理这些数据。 

作者在本文中设计的汉字数据库共包括了三个表, 

荔 223

分别是“汉字基本资料表”、“汉字闭合曲线编号 

32 1 

8g01 0 4356

0 

 

33 1 1 

表”和“汉字坐标数据表”。 

34 1 2 

“汉字基本资料表”有四列数据(如图2所 

示)。第一列是ID号,其作用主要用于排序;第二 

图3汉字闭合曲线编号表 

Fig.3 The code table of close llne 

列为汉字或字符在数据库中的唯一编号;第三列为 

的闭合曲线对象的数目,但却没有对每一个曲线对 

具体的汉字或字符;第四列是每一个汉字或字符包 

象进行编号。因此,在后二张表中设计了“闭合曲 

含闭合曲线的数目。 

线编号”,就是为每一个闭合曲线对象进行编号。 

“汉字闭合曲线编号表”(如图3所示)的主要 

“汉字坐标数据表”(见图4)包含了五列。第 

作用是为每一个汉字所包含的闭合曲线对象进行 

列是ID号,功能与前面二个表相同;第二列“汉 

编号。它包括了三列,第一列ID号(作用与汉字 

字编号”与“汉字基本资料表”中的汉字编号相同; 

基本资料表的ID字段相同);第二列“汉字编号” 

第三列“闭合曲线编号”与“汉字闭合曲线编号表” 

与图1中的“汉字编号”相对应。虽然在“汉字基 

中的“闭合曲线编号”相同。表的最后二列分别记 

本资料表”中已经记录下了每个汉字或字符所包含 录了字体轮廓控制点的 、Y坐标。 

网 溜瞪驽giC- ̄J E疆 一 

疆黼疆鞫 阔鼹爨 露I1.1鞭疆龋骚露圉黼鹱鼹鼹骥 疆蘑 鹱 爨 

玉-0 0 .092 1 015 0 

2 0 0 .094 .9E.2 0 

爨 3 0 0 .095 .902 0 

雾 

爨 

45

 

 

0 

 0

 

 

09

96"

8 

f .8T

36

68

52 

 

 

 

骥 T 0 0 .09B .59l 0 

8 0 0 .098 .503i 0 

9 0 0 .OgT .422 0 

10 0 0 .096 .34B 0 

雾 l12l 0 0 .0O954 .28235 0 

图4汉字坐标数据表 

Fig.4 The coordinate table of Chinese words 

维普资讯

l74 物探化探计算技术 29卷 

考虑到每种汉字字体矢量字库只有数十兆字 

节,上述数据库用ACCESS平台实现。通过以上三 

个数据表的建立,将汉字与其对应的坐标联系在一 

起,方便了后续程序对汉字的访问与数据导出。三 

张表的矢量汉字字体数据,可以用前述的代码,略 

加改变,直接输出到这些表中即可。 

汉字中每一个闭合曲线对象的编号(见图3)。 

strSq1.Format(”select from汉字闭合曲线编 

号表where汉字编号= %s,,,,m_ChineseCode); 

//构造SQL语句 

_

pReeordset一 

. 

>Open(一variant—t(strSq1),in—pConnection.Get— 

InterfacePtr(),adOpenDynamic,adLockOptimistic, 

adCmdText); 

4汉字输入与GOCAD汉字曲线对 

象的形成方法 

在GOCAD中的汉字显示与其它图形处理软 

件中的汉字显示有类似的方式和特点,除了可以输 

入汉字或字符外,还需要满足用户对字体、尺寸 

(放大倍数)、字间距、排列方式等的显示要求。为 

此,在本文中特别设计了满足这些要求的汉字输入 

的程序界面(如图5所示)。 

图5汉字输出程序界面 

Fig.5 The output platform of Chinese words 

要实现汉字的输人,第一步是根据用户输人的 

汉字,从“汉字基本资料表”中找出汉字对应的唯 

编号(见图2)。具体代码(C++)实现是: 

strSq1.Format(”select木from汉字资料表 

where汉字= %Sm,re_Chinese); 

_

pRecordset—— 

>Open(一variant_t(st ̄Sq1),in—pConnection. 

GetInterfacePtr(),adOpenDynamic,adLock・ 

Optimistic,adCmdText);var:in—pRecordset 

>GetCollect(”汉字编号”); 

_

ChineseCode:(LPCSTR)(_bs )vat; 

其中,in—pRecordset是一ReeordsetPtr类型的指 

针;m_pConnection ̄_ConnectionPtr类型的指针。 

上面的程序通过构造一个SQL语句,利用打 

开满足SQL语句的记录集,从记录中通过取出汉 

字所对应的唯一编号赋给一variant—t类型的变量 

var,最后将var强制类型转换成CString类型,并赋 

给变量m_ChineseCode。 

程序实现的第二步是根据找出的汉字编号in— 

ChineseCode,再从”汉字闭合曲线编号表”中获取 

//打开满足SQL语句条件的记录集 

linecount=m

_

pRecordset一>RecordCount; 

//获得汉字中闭合曲线对象的数目 

_

LinePartCode=new CString[1inecount]; 

for(1ong i=0;i<linecount;i++) 

{ var=in—pRecordset一>GetColhet(”闭 

合曲线编号”);//获得闭合曲线对象 

编号 

_

LinePartCode[i]=(LPCSTR)(一bstr~ 

t)vat; //强制类型转换 

_

pRecordset一>MoveNext();} 

//移到下一条记录 

以上程序将汉字闭合曲线对象的编号存人 

CString类型的m_LinePartCode数组中。 

程序实现的第三步是获取汉字每一闭合曲线 

对应点的坐标。下面的代码实现了从数据库中取 

出单个汉字或者字符所有控制点的坐标,并分别存 

人三个数组中。具体如下: 

strSq1.Format(”select from汉字坐标数 

据表where汉字编号= %S ,m_ChineseCode); 

//构造SQL语句 

_

pRecordset—— 

>Open(一varinat—t(st ̄Sq1),in—pCon— 

nection.GetInterfacePtr(),adOpcnDynamic,adLock— 

Optimistic,adCmdText); 

//打开记录集 

_

pRecordset一>Sort=”ID ASC”: 

//用于按照ID号排序 

recordcount=m

pRecordset一>Record— 

Count; //获得每个汉字在数据库中包含记录的 

数目 

lfoat木x

木z

木Y

; 

//定义三个数组用于存放所有闭合曲线 

对象的X,Y,z坐标 

CString m

_

Code: 

//用于存放所有闭合曲线编号 

维普资讯

2期 朱焱辉等:GOCAD矢量汉字数据库的开发 175 

x=new float[recordcount];Y=new float 

{/ m_Zoom表示图5中用户输入的放 

[recordcount];z=new lfoat[recordco吼t]; 

大倍数,m_Xeord,m_Ycord,m_Zcord表示用户输 

_

Code=new CString[reeordeount]; 

入的x、Y、z的起始坐标,x_move和y_move是与 

for(1ong j=O;j<recordcount;j++) 

字体排列方式和汉字间距有关的变量 / 

//读出编号和坐标数据 

xx[k]=m_XCodr+(x[i] m—Zoom)+ 

{ vat=m—pReeordset一>GetColleet(” 

闭合曲线编号”); 

yy[k]=m_YCord+(Y[i] m_Zoom)+y 

Code[j]=(LPCSTR)(一bstr—t) 

_

move;ZZ[k]=m_ZCord+Z[i];k++;} 

vat"; 

else 

vat"=m

pReeordset一>GetColleet 

_

(”x”);x[j]=float(var.fltVa1); 

//表示同一个闭合曲线对象的坐标点已经判断完 

毕,然后调用生成GOCAD闭合曲线对象的函数。 

vat"=m

_

pReeordset一>GetColleet 

(”Y”);Y[J]=float(vat".fltVa1); 

{mypline.GOCADP ̄ne(强,YY,zz,k);k=O; 

ak;} 

vat"=m

_

pReeordset一>GetColleet 

bre

(”z”);z[j]=float(vat".fltVa1); 

if(I==recordcount一1)//表示一个汉字 

pReeordset一>MoveNext();} 

的最后一个闭合曲线对象 

_

//移动到下一记录 

{mypline.GOCADP ̄ne(强,YY,zz,k);k=0; 

_

pReeordset一>Close(); 

break;} 

//关闭记录集 

}} . 

程序实现的第四步是将每一个闭合曲线以及 

以上四步程序组合到一起,通过循环的方式可 

它们的控制点全部分开,成为单个的闭合曲线对 

以将用户输入的所有汉字和字符一起生成GOCAD 

象,再调用生成GOCAD闭合曲线对象的函数,完 

的一个闭合曲线对象文件,然后调用MyPLine的成 

成数据的转换。 

员函数GOCADSave()将数据存储到磁盘上。 

上面的程序中用到的MyPLine变量是用GO— 

lfoat xx, YY, zz; //用于存放每个闭合 

CAD的标准线对象类Pline来定义的。Pline类主 

曲线对象控制点坐 

要包括三个函数:GOCADCrea ̄ne、GOCADPLine 

标 

和GOCADSave。 

xx=new float[reco ̄count];yy=new float 

程序实现的第五步是:在GoCAD中,为了将 

[reco ̄count];ZZ=new float[record— 

汉字控制点坐标数据转化成闭合曲线对象,首先需 

count]; 

要将控制点坐标数据转化成GOCAD的空间点 

//reeordeount表示每个汉字在数据库中 

Point3d对象;然后由Point3d对象构造原子Atom; 

. 

包含记录的目 

再由原子Atom对象构造节segment对象;最后将 

i=0;k=0;mypline.GOCADCrea ̄Une(out一 

所有的节segment连接起来,构成GOCAD的闭合 

¥avenalne);//mypline是MyPLine类型的变量out- 

曲线对象。下面是C++代码实现。 

¥avenalne是输出文件名,MyPLine是 

ILine iline;PLne pline

对GOCAD进行开发产生的新类 

_

tmp;SegUse 

for(j=O;j<linereeordeount;j++) 

 ・segment=nil;PtrList<SegUse>segs; 

{ //linereeordeount表示每个汉字所包 

PtrList<ILine> ilines; 

含的闭合曲线对象的数目 

pline

_

tmp=pline::create(savename); 

ofr(;i<recordcount;i++) 

//创建Pline对象 

{if(m—Code[i]==m—LinePartCode 

iline=pline

_

tmp一>create_element(); 

[j]) 

//由Phne对象创建一个Iline 

/ 如果第i个坐标点所对应的闭合曲线对象编号 

对象 

与第j个闭合曲线对象编号相同,即这些坐标点都 

Point3d point=new Point3d[Number]; 

属于同一个闭合曲线对象,则将这些点的坐标连同 

//定义三维空间点数组 

放大倍数以及其它参数重新存入新的数组中。 / 

Atom atoms=new Atom 『Number]: 

维普资讯

176 物探化探计算技术 

//定义原子即含有属性的三 

维空间点 

29卷 

for(1ong i=0;i<Number;i++){ 

//给三维空间点和属性数组 

赋值 

・point[i]=Point3d(float(x[i]),float(Y 

[i]),lfoat(z[i]));//由坐标构造GOCAD的空 

间点对象 

atoms[i]=iline一>create—atom(point 

[i]); //用于构造出原子 

} 

for(1ong i=1;i<Number;i++){ 

//调用ILine的成员函数由原 

子构造节对象(segment) 

segment=iline一>create

_

图6一个汉字字符串在GOCAD软件中四种字体的 

显示对比结果 

Fig.6 The output result of Chinese words in GOCAD 

simplex(atoms[i 

5结论 

为了在GOCAD地质建模软件中实现三维汉 

1],atoms[i]); 

} 

segment=iline一>create

simplex(atoms[Num— 

ber一1],atoms[0]);//将Iline起始点连起来构成 

闭合曲线对象 

segs.append(segment); 

//将节对象添加到节对象列 

表中 

以上程序将汉字中单个的闭合曲线对象用 

GOCAD的Segment表示出来,然后将该节对象添 

加到节列表segs中,通过循环的方式就能将所有 

汉字的所有闭合曲线对象以sement的形式添加 g

到节列表segs中,用于最终构成GOCAD的PLine 

对象pline—tmp。 

程序实现的第六步是将前述程序形成的汉字 

字体轮廓曲线保存,形成GOCAD能够接受的对象 

文件。代码如下 

pline

tmp一>init(segs,ilines,re,e); 

//由节对象列表segs生成PLine的 

_

字的显示,作者在文中提出的利用CoreDraw绘图 

软件提取矢量汉字,建立矢量汉字数据库,并将之 

在GOCAD中输入和显示的方案是成功的。实际 

上,上述汉字的实现方案,完全可以移植到一些只 

能在工作站上运行的大型图形处理和三维可视化 

软件上。 

参考文献: 

[1] 朱焱辉,朱培民,金丹.从&reGis平面栅格图形到 

GOCAD三维图像转换的开发探讨[J].工程地球物 

理学报,2004,l0(5):435. 

[2]张立科.Visual C 6.0数据库开发技术与工程实 

践[M].北京:人民邮电出版社,2004. 

[3]李村合.VC 应用程序中ODBC数据源的自动注 

册[J].物探化探计算技术,2003,25(1):88. 

[4] 张丽莉,吴健生,王家林.地学数据文件向Shapefile 

文件的转换[J].物探化探计算技术,2004,26(1): 

78. 

对象pline_tmp 

GObj group=(GObj )pline—tap;r 

//将Pnne的对象指针强制转换成 

[5]冯德山,戴前伟.用Visual C 

231. 

开发地质雷达正演 

模拟软件[J].物探化探计算技术,2004,26(3): 

[6]汤彬,陆玲.用VC开发Windows字符曲线类[J]. 

物探化探计算技术,2000,22(3):282. 

[7]陈志远,赵程.VC环境下AutoCAD图形实体的二次 

C,obj类型的指针 

gobj::save(group); 

//调用Gobj的成员函数保存数据 

前述的六步程序,完整实现了将用户输入的汉 

字或者字符串显示在GOCAD软件的过程。图5 

和图6是一个用户输入“中华人民共和国”的汉字 

字符串,并在GOCAD中显示出四种字体对比结果 

的例子。 

开发[J].现代制造工程,2006,8:54. 

作者简介:朱焱辉(1979一),男,汉族,四川泸州 

人,硕士,主要研究方向:地球探测与信息技术。