電火花線切割切割漢字的編程技巧
電火花線切割要實現(xiàn)切割漢字首先要獲得漢字字形輪廓,這涉及到如何從字庫中提取漢字字形輪廓的問題。漢字的字體根據(jù)其實現(xiàn)形式的不同可分為點陣字體、矢量字體及TrueType字體等幾種。其中使用最廣泛的為TrueType字體,與其他字體相比,TrueType字體具有明顯的優(yōu)點:
(1)它使用直線和曲線對字符進行描述,具有放大和縮小不變形的特點;
(2)具有處理速度快及與設(shè)備無關(guān)的特點;
(3)它是Windows系統(tǒng)所使用的最廣泛的字體,因而Windows提供了大量的API函數(shù)來支持和處理這種字體,利用這些函數(shù)可方便地對TrueType字符進行各種處理,如旋轉(zhuǎn)、變形等。
在TrueType字體中,字形輪廓是由一些直線和曲線的集合及一些對字體的描述信息所組成,這些直線和曲線定義了TrueType字體及符號的外形輪廓,而那些字體的描述信息則用來控制和調(diào)整直線的長度和曲線的形狀,主要用來調(diào)整字形輪廓尺寸,使用這些描述信息可對TrueType字體或符號在保持其原始形狀的情況下進行放大、縮小等處理。
Windows提供了許多函數(shù)來處理TrueType字體,其中與提取字形輪廓有關(guān)的最主要的函數(shù)為GetGlyphOutline,它可用來提取被選擇到指令設(shè)備環(huán)境(如內(nèi)存、顯示設(shè)備等)的字符的輪廓或位圖。在Windows
API中,GetGlyphOutline函數(shù)聲明如下:
DWORD GetGlyphOutiline(
HDC hdc,∥設(shè)備環(huán)境的句柄
UINT uChar,∥所要查詢的字符
UINT uFormat,∥所要返回的數(shù)據(jù)類型
LPGLYPHMETRICS lpgm,∥指向字符規(guī)格結(jié)構(gòu)的地址
DWORD cbBuffer,∥數(shù)據(jù)緩沖區(qū)的大小
LPVOLD lpvBuffer,∥數(shù)據(jù)緩沖區(qū)的地址
CONST MAT2*lpmat2,∥變換矩陣結(jié)構(gòu)的地址);
其中的主要參數(shù)說明如下:
uChar:指定所要查詢的字符,對漢字來說是指漢字的編碼,如:GB-2312和Unicode等編碼。
uFormat:指定函數(shù)所要提取的數(shù)據(jù)的格式,可取下面一些值:GGO_ITMAP、GGO_NATIVE、GGO_METRICS、GGO_GRAY2_BITMAP、GGO_GRAY4_BITMAP、GGO_GRAY8_BITMAP。
對于提取字符的字形輪廓來說,由于只需得到字形輪廓的二值圖象,不用得到灰度圖象,因此uFormat參數(shù)可取兩個值:GGO_BITMAP、GGO_NATIVE。如取GGO_BITMAP,函數(shù)將返回字符的字形輪廓位圖;取GGO_NATIVE,函數(shù)將返回用來描述字符外形輪廓的曲線的點的數(shù)據(jù),使用的單位是字體設(shè)計的單位,如uFormat參數(shù)取值為GGO_NATIVE,則任何lpmat2參數(shù)指定的變換矩陣將被忽略。由于可能需對提取出的字形輪廓作一定的變換處理(如:放大、縮小、旋轉(zhuǎn)及改變縱、橫比等),將參數(shù)uFormat的值設(shè)置為GGO_NATIVE。
調(diào)用GetGlyphOutline,函數(shù)將返回一系列的折線和樣條曲線,返回的折線和曲線的信息存儲在一個
TTPOLYGONHEADER結(jié)構(gòu)及緊隨其后的多個TTPOLYCURVE結(jié)構(gòu)中,這些信息主要為描述折線和曲線所需的點的坐標(biāo),要描述字形輪廓須使用這些信息。上述兩個結(jié)構(gòu)中所有的點都以POINTFX結(jié)構(gòu)形式返回,這些點描述的是絕對位置而不是相對位置。要描繪一個TrueType字符的字形輪廓,須同時使用折線和曲線。TTPOLYGONHEADER結(jié)構(gòu)中的pfxStart成員返回字形的封閉輪廓的起始點,也是封閉輪廓的終止點。
下面對其中幾個重要的數(shù)據(jù)結(jié)構(gòu)作簡要的說明。
其中,TTPOLYGONHEADER結(jié)構(gòu)指定一個TrueType字符的字形輪廓的起始點及該輪廓的類型(直線或曲線)。其定義為:
typedef struct_TTPOLYGONHEADER{//ttph
DWORD cb;
DWORD dwType;
POINTFX PfxStart;
}TTPOLYGONHEADER,FAR.LPTTPOLYGONHEADER;
其中成員cb指定描述字形輪廓的TTPOLYGONHEADER結(jié)構(gòu)和TTPOLYCURVE結(jié)構(gòu)所需的字節(jié)數(shù);dwType字符的輪廓類型;pfxStart指定輪廓的起始點。
TTPOLYCURVE結(jié)構(gòu)中包含了TrueType字符中有關(guān)字形輪廓曲線的信息。其定義為:
typedef struct tagTTPOLYCURVE { // ttpc
WORD WType;
WORD Cpfx;
POINTFX apfx [1];
} TTPOLYCURVE,FAR*LPTTPOLYCURVE;
其中成員wType指定TTPOLYCURVE結(jié)構(gòu)所描述的曲線類型,可有兩個取值;TT_PRIM_LINE和TT_PRIM_OSPLINE,分別代表曲線是折線和B樣條曲線;cpfx指定數(shù)組中POINTFX結(jié)構(gòu)的數(shù)目;apfx指定一個確定折線或者B樣條曲線的POINTFX結(jié)構(gòu)類型的數(shù)組。
POINTFX結(jié)構(gòu)中包含用來描述TrueType字符字形輪廓的點的坐標(biāo),其定義為:
typedef struct tagPOINTFX { // ptfx
FIXED X;
FIXED Y;
} POINTFX,
其中X和Y分別代表點的橫、縱坐標(biāo)。
在調(diào)用GetGlyphOutline函數(shù)得到描述字形輪廓的數(shù)據(jù)后,要將其描繪出來還需調(diào)用繪制直線和曲線的函數(shù)。一個TrueType字符由折線和二次樣條曲線描繪而成,調(diào)用GetGlyphOutline函數(shù)返回了描繪這些折線和曲線所需的點的有關(guān)信息,這些信息存儲在TTPOLYGONHEADER和TTPOLYCURVE結(jié)構(gòu)中,根據(jù)其中的成員wType所指定的不同值,來調(diào)用Windows
API所提供的相關(guān)繪制折線和樣條曲線的函數(shù),即可繪制出字符的字形輪廓。在繪制時還可根據(jù)需要對字形輪廓進行各種處理,如放大、縮小、旋轉(zhuǎn)及改變字符的縱橫比等。圖1顯示了采用以上方法提取的“電”字的字形輪廓。
圖1 “電”字的字形輪廓
還有一個需解決的問題是如何獲得漢字編碼的問題。通常漢字是以字符串的形式輸入計算機的,要調(diào)用GetGlyphOutline函數(shù)得到某一漢字的字形輪廓,還須得到該漢字的編碼(一般指GB-2312編碼,在Windows
NT和Windows
2000下可使用Unicode編碼),用來指定GetGlyphOutline函數(shù)中的uChar參數(shù),這就需進行由字符串到漢字編碼的轉(zhuǎn)換。下面給出了用Delphi實現(xiàn)的由漢字字符串到漢字的GB-2312編碼的轉(zhuǎn)換函數(shù),該函數(shù)的輸入?yún)?shù)為字符串的形式的單個漢字,返回值為輸入?yún)?shù)漢字的GB-2312編碼。
function CodeConvert(s:string):interger;
begin
result:=ord(WORD(s[1]shl 8)+WORD(s[2]));
end;
3 字形輪廓二值圖象的轉(zhuǎn)化及其編輯處理
由于受線切割機所能切割圖形形狀的限制,即在不重新穿絲的情況下,只能切割一筆畫成的圖形;加上漢字?jǐn)?shù)量眾多,字形千變?nèi)f化,且大多數(shù)漢字都不能一筆寫成,因此將漢字的字形輪廓提取出來后并不能直接用于切割,還需對其進行一定的編輯處理,使其符合線切割加工的需要,即把它變成能一筆寫成的切割軌跡。且實際應(yīng)用中,多數(shù)情況下可能不是切割單個漢字而需一次切割多個漢字,這也要進行編輯處理。而要進行編輯處理,首先要將圖形轉(zhuǎn)化為圖象。還是以“電”字為例,在未經(jīng)編輯處理時,在線切割機上只能切割出如圖2所示的不完整字形,在經(jīng)過適當(dāng)?shù)木庉嬏幚砗螅€切割機就可加工出如圖3所示的完整漢字的字形了。
圖2 未經(jīng)編輯處理時線切割機所能加工的“電”字字形輪廓
圖3 編輯處理后線切割機所能加工的“電”字字形輪廓
因為我們只需標(biāo)識字形的邊界輪廓,因此將其轉(zhuǎn)化為二值圖象即可。將字形輪廓轉(zhuǎn)化為二值圖象,也就是將其轉(zhuǎn)化為一個用矩陣表示的象素點圖象,矩陣中的每一位都是二進制數(shù),當(dāng)該位為1時表示字符的筆劃經(jīng)過此位,該位為0時表示字符的筆劃不經(jīng)過此位。因為只要分辨出某點為0還是1,因此每個點只要用一位二進制數(shù)表示即可,這樣1個字節(jié)就可以表示8個象素點,但為方便敘述本文采用以1個字節(jié)表示1個點來進行說明。
要將字形輪廓轉(zhuǎn)化為二值圖象,首先根據(jù)需要(如字體、尺寸大小、縱橫比、是否旋轉(zhuǎn)、變形等)在屏幕上繪制出所要切割字符的字形輪廓;然后對圖形進行掃描,將有筆劃通過的點(對應(yīng)于與字符顏色相同象素的位)的值置為1,而其它的點則置為0,掃描完畢后便將字形輪廓轉(zhuǎn)化為二值圖象了。
生成二值圖象后還需對圖象進行適當(dāng)?shù)男薷模詽M足線切割加工的需要。對圖象進行編輯處理,可用一個小方塊代替一個放大了的象素,通過建立網(wǎng)格編輯區(qū),每一網(wǎng)格小方塊都是一個放大了的象素,這樣可對每個象素進行編輯處理,控制鼠標(biāo)在相應(yīng)的網(wǎng)格眼內(nèi)填入字符或背景顏色,同時填入字符顏色所對應(yīng)的位置為1,填入背景顏色所對應(yīng)的位置為0。
4 切割指令的生成
將漢字的字形輪廓轉(zhuǎn)化為二值圖象且編輯處理后,為生成切割指令須用直線或圓弧對其進行描述,由于漢字字形較適合用直線來對其進行描述,因此采用直線段來實現(xiàn)對漢字字形的描述。
由于線切割機所能切割的圖形具有一定的特殊性(即需能以一筆畫完),因此只需采用某種算法對圖進行一次遍歷便可得到加工軌跡。
要對圖象進行遍歷,首先需確定搜索策略。由于能被切割的圖形具有特殊性,采用改進了的深度優(yōu)先搜索方法來對圖象進行遍歷。主要思想為:先確定圖象的起始點,然后沿逆時針方向在該點周圍尋找下一點,找到后沿著這兩點確定的方向繼續(xù)搜索,直至將該方向上的點搜索完畢,然后回溯,以回溯得到的點為基礎(chǔ)重復(fù)以上搜索,直至所有點都被搜索過,在搜索過程中將經(jīng)過的點的值從1置為0,同時記錄所經(jīng)過的直線。
下面介紹一下所要用到的主要數(shù)據(jù)結(jié)構(gòu)。
記錄直線所用結(jié)構(gòu)為TLineRecord,它用來記錄每段直線的起點和終點坐標(biāo),其定義如下:
TLineRecord=record
StartPoint, EndPoint: TPoint; //直線起始點,終止點
end;
PLineRecord=^TLineRecord;
其中StartPoint, EndPoint分別為直線的起點和終點。
圖象采用二維數(shù)組進行表示,首先按照行、列從小到大的順序找到圖象的起始點,然后再采用逆時針方向來搜索下一點。搜索方向的定義為:
SearchDirection:array[0..7,0..1] of
interger=((1,0),(1,-1),(0,-1),(-1,-1),(-1,0),(-1,1),(0,1),(1,1));
遍歷算法如下:
(1)掃描圖象尋找起始點,將其坐標(biāo)記為(k,1);用FirstPointX、FirstPointY記錄第一點橫、縱坐標(biāo)的值;
(2)初始化記錄直線的指針,建立記錄直線的鏈表;將起始點的k,1值作為直線起點和終點的橫、縱坐標(biāo),將該直線加入到直線紀(jì)錄的鏈表中去;
(3)以第一點為基準(zhǔn)點沿逆時針方向?qū)ふ蚁乱稽c,如果搜索到值為1的點則記搜索方向為i,該點的橫、縱坐標(biāo)記為(k,1),將記錄直線的終點橫、縱坐標(biāo)設(shè)置為k,1;
(4)置是否搜索完畢標(biāo)志SearchCompleted為False;
(5)如果SearchCompleted不為True則重復(fù)作6-13步;
(6)置SearchCompleted為True;
(7)置是否同一條線標(biāo)志SameLine為True;
(8)如果SameLine為True則重復(fù)作9-12步;
(9)置SameLine為False;
(10)沿i方向進行搜索,即k:=k+SearchDirection [i][0];1:=1+SearchDirection [i][1];
(11)如果點(k,1)為1,則置SameLine為True;將直線的終點坐標(biāo)設(shè)置為(k,1);將點(k,1)的值設(shè)置為0;
(12)如果點(k,1)為0,則置SameLine為False;
(13)以點(k,1)為基準(zhǔn)點沿逆時針方向?qū)ふ蚁乱稽c,如果搜索到值為1的點,則記搜索方向為i;在直線記錄列表中增加一條新的直線,k,1值作為直線起點的橫、縱坐標(biāo);將搜索到的點的橫、縱坐標(biāo)記為(k,1),將直線終點的橫、縱坐標(biāo)設(shè)置為(k,1);置Searhcompleted為False,置SameLine為True;將點(k,1)的值設(shè)置為0;
(14)進行圖形封閉化處理,在直線記錄列表中增加一條直線,將k,1值作為直線起點的橫、縱坐標(biāo),F(xiàn)irstPointX、FirstPointY作為直線終點的橫、縱坐標(biāo)值。
這樣當(dāng)遍歷完成后,遍歷的軌跡就保存在直線記錄列表中了,也就是說已實現(xiàn)將漢字的字形輪廓用直線段進行描述了。需指出的是,由于漢字字形本身或者編輯處理的原因,在進行圖象遍歷的過程中,可能存在一些不和諧的點,使遍歷不能完成(如存在斷點、尖點及多余點的情況),需在遍歷之前運用圖象處理的技術(shù)將這些點補足或者剔除掉,以使遍歷能順利完成,有關(guān)這方面的算法不再贅述。
至此要實現(xiàn)切割漢字就只剩下如何生成切割指令的問題了。由于已將漢字的字形輪廓用直線進行描述,且這些直線還首尾相接組成一個封閉輪廓,要生成線切割機的切割指令,只需按切割指令的要求將這些直線進行轉(zhuǎn)換即可。
本文由中走絲,線切割機床,電解去毛刺,去毛刺設(shè)備-蘇州中航長風(fēng)數(shù)控科技有限公司采集整理發(fā)布。
更多線切割,穿孔機,電化學(xué)去毛刺文章資料請參考www.szcfedm.com www.zhchangfeng.com www.skwedm.com