细说元笔画

 

在搞汉字笔画组字时,必须用50种左右的汉字笔画。比较起来,英文字母似乎简单得多,好像可以只要半圆弧和直线段两种。实际却不然。因为半圆弧和直线段,都可有4种不同的方向,那就要8种元笔画。而且这8种元笔画,仍难以组成其它ASCII字符,此外还有大量各种拼音文字的不同字母及形态各异的日本假名。…………说实在,当我给自己提出这个任务后,很长一段时间里,还搞不清“元笔画”到底应该是怎样的。

经过反复摸索,慢慢变得清楚起来。现在我说的一个“元笔画”,是指可由简单的小程序画出的一类图形,文后附有最后使用的VB子程序。目前共7类,毎类用一个ASCII字符加几个参数(即字符串),就可画出需要的图形,再由它们组合成所有非汉字字符。这些类是:

 

 元笔画名称    代表字符

1.线段            

    2.圆孤           @ 

3.螺旋形          &  

4.多角形         #  

5.波形           $

   6.不定形         %   

7.任意曲线       

 

我虽然把汉字库里的所有ASCII及其他非汉字字符都用这样的“元笔画”组出来了。但离我的最高目标(由它们能够很方便地组出所有文字,或所有字母),还很远,组出的字形也很差,还需要研究和创造。最后会成为什么样子,很难预料。汉字笔画也应该由元笔画组出。您看到,比笔画复杂得多的平假名都已用元笔画组出来了,组出所有汉字笔画是不困难的。这样,计算机真的不需要任何字模,完全无字库了。当然,常用的字母、字符、汉字笔画、字根等,应该有一定的标准写法,最好指定一个标准字符串并规定其内码。但它已不是现在意义下、用.ttf文件存贮的的字库了。如果仍要称它为字库,那么全世界就只有这一个字库,内码长度不超过2字节,所有文字都由它们组出。还可以写出种种符号,例如任意的八角星、十角星、十二角星,各种形状的序数符(如写在六角形内的序数)等等。

现在对现有的7种元笔画进一步进行解说。实际上只要说清下面的《元笔画各参数意义表》就可以了。每个元笔画是用一个“首符”再加几个作为参数的字符组成的串来表示的。前6种元笔画的参数都是数字0-9,前5种元笔画的参数最多只有5个,即表中列的a1~ a5,且可以缺省,各有一定的缺省值。例如无参数的一个字符“!”,是一水平线,缺省的参数值a1=0,位置在正中a2=5,宽度最小 a3=1,长度最大a4=9。实际用到绘图语句中,要乘以括弧内的数字,因为直线长度是从中点开始算的,所以少一半。a1不为0时,a1*18是直线的斜角,5*18=90度,所以“!5”就是一根位在中间的垂线,参数a1>5,则是向后倒的。参照此表,再在计算机上试验一下,不难得到需要的元笔画。

圆孤@的参数a1<6时,是简单的圆环,调节参数a2,可增环宽直至成黑圆点。参数a1>=6时,才是圆弧(有开口的圆环), a1603是开口方向,0向右,1向上,2向左,3向下。开口角度等于a2*30,最大是240度。特别设a2=9,生成U字形,即开口是180度,与a2=6一样,但开口两边各接一段直线段,开口向上时,就是U,开口向其它3个方向,则是数学符号。这个元笔画的轮廓线主要由两个圆在两开口点连接而成。外圆固定为最大,内圆按宽度a3而缩小。a4=0时,两圆是同心圆,为了生成字符“C”,内圆要向右偏,弧的左边就比开口处宽厚,故要用串“@6311”。

螺旋形&的参数a1<3时,是发散的圆螺旋线,大于3时,则是螺旋折线,a1指一圈折线的角数。用a3还可整体顺转一定角度,以满足需要(上一个圆孤@的参数a5,下一个星形#的参数a3,也是起同样的作用)。

星形#的参数a3=0时,是实心的星形,a2为星形的内圆(星体)大小。a3>0时,实为多角形,如五角星应为“#221”,而“#22”则是有五个光芒的星形。

波形$的诸参数,意义清楚,用不着再加说明。

不定形%的参数一定要刚好是11个数字。a1外的5对数字描述两条曲线,毎条曲线5个点。如果a1是偶数,曲线的走向是横向的,那么它们都在均匀分布的5条垂直线上,首尾两点在字符空间的左右两端,而毎对数字分别是上下两条曲线的纵向坐标。如果a1是奇数,毎对数字是分别是左右两条曲线的横向坐标。而a1的大小,则规定曲线是否经过平滑化,表中说得很清楚。例如字符“【”的串为“%55957565759”,a15,是奇数,曲线纵向,左曲线的横坐标都为5,是位居中部的垂直线,不平滑,右曲线横坐标依次是97679,曲线经平滑成凸向左边的圆弧。

任意曲线~的参数,是唯一可以用英文字母的,参数个数原则上无限制(实际受可存贮的字串长度的限制)。它是把写字符的空间,平分为8*7个方格,每个方格的位置指定一个字符表示,如表末尾所示。这样,一个字符串就可连一条折线,如果要多条线,中间可用0隔开(0不是点)。第一个参数a1是数字时,是指定曲线的宽度,如果是字母,则认为a1=0a1还有区分曲线性质的作用,当a1<5时,曲线是平滑曲线,曲线的宽度等于a1+1a1>5时,则是折线,宽度等于a1-4。日文片假名就可用这种元笔画生成,如串“~Cb0QLW0dO7ElvX”就会画出“ぁ”。

这些元笔画可以和汉字笔画、字根、汉字或其他字符本身,再组成更复杂的字符。这时,单个元笔画的结构属性是上下结构。要改为左右结构时,后加结构符“”。如果加“=”号,后面的笔画将叠加其上。要调节笔画位置,可用空白符Z,象汉字笔画组字中的z

 

 

 

 

元笔画各参数意义表

元笔画 首符  参数a1       a2       a3       a4        a5

线段   !   直线斜角 (*18)  水平位置(*70)  直线宽度    直线长度(*40)

      0为水平线     垂直位置(*70)  直线宽度    直线长度(*40)

圆孤   @  <6为圆径     圆环宽度1-9 

        -6为开口方向   开口角度(9U) 圆弧宽度1-9   内圆心偏离程度  整体顺转角度(*5

螺旋形  &  2,1,0有圆心   旋线宽=旋线隙  整体顺转角度     

       >=3为一周角数   旋线宽=旋线隙  整体顺转角度     

星形   #   星形的角数(+3)   星形的内圆大小  0        旋转角度

       多角形的角数(+3)  间a2-1角连直线 连线宽度    旋转角度

波形   $   波数        波幅       波线宽度    a4>0,波向垂直

不定形  %  a1指定曲线的特性:奇数,方向垂直,等于1;;5时,分别为两边;左边;右边已经平滑,否则是折线

                 偶数,方向水平,等于0;;4时,分别为上下;上边;下边已经平滑,否则是折线          

        第二个数开始的10个数串指定的点组成封闭曲线。第0246813579个数分别成左右两曲线。

任意曲线 ~      a1<5时为平滑曲线宽度(+1),a1>5时是折线,宽度为a1-4

任意曲线形由依次的符号点连成,各符号平面位置如下(碰到0则中断):

1  A  I  Q  a  i  q

2  B  J  R  r  j  r

3  C  K  S  c  k  s

4  D  L  T  d  l   t

5  E  M  U  e  m  u

6  F  N  V  f  n  v

7  G  O  W  g  o  w

8  H  P  X   h  p  x

 

 

 

 

 

 

 

           画元笔画的子程序txdrw

 

Sub txdrw(p)

'p指定的pictureBox中,画已由zganalys分析,并记在zz中的元笔画图形

pp = p

Dim Pt(280) As POINTAPI                                         '多边形顶点变量数组

Dim Pts(10) As POINTAPI

Dim hRgn, hBrush As Long                                        '多边形句柄,画刷句柄

pi = 3.1415926535

z = Left(zz, 1): zz = Trim(zz)

a1 = Val(Mid(zz, 2, 1)): a2 = Val(Mid(zz, 3, 1))

a3 = Val(Mid(zz, 4, 1)): a4 = Val(Mid(zz, 5, 1)): a5 = Val(Mid(zz, 6, 1))

Select Case z

    Case "!"               '线段

        a1 = pi * a1 * 18 / 180                                        'a1为直线角度

        If a2 = 0 Then a2 = 5

        a2 = a2 * 70                                                   'a1=0时为a2为直线垂直位置,否则是水平位置

        If a3 = 0 Then a3 = 1

        If a4 = 0 Then a4 = 9

        a3 = Atn(a3 / a4 / 2)                                          'a3为直线宽度

        a4 = a4 * 33                                                   'a4为直线长度

        If a1 > 0 Then a4 = a4 / Sin(a1)

        If a1 > 0 Then

            Pt(0).x = a2 + a4 * Cos(a1 - a3): Pt(1).x = a2 + a4 * Cos(a1 + a3): Pt(2).x = a2 + a4 * Cos(pi + a1 - a3): Pt(3).x = a2 + a4 * Cos(pi + a1 + a3)

            Pt(0).y = 350 - a4 * Sin(a1 - a3): Pt(1).y = 350 - a4 * Sin(a1 + a3): Pt(2).y = 350 - a4 * Sin(pi + a1 - a3): Pt(3).y = 350 - a4 * Sin(pi + a1 + a3)

        Else

            Pt(0).x = 350 + a4 * Cos(a1 - a3): Pt(1).x = 350 + a4 * Cos(a1 + a3): Pt(2).x = 350 + a4 * Cos(pi + a1 - a3): Pt(3).x = 350 + a4 * Cos(pi + a1 + a3)

            Pt(0).y = a2 - a4 * Sin(a1 - a3): Pt(1).y = a2 - a4 * Sin(a1 + a3): Pt(2).y = a2 - a4 * Sin(pi + a1 - a3): Pt(3).y = a2 - a4 * Sin(pi + a1 + a3)

        End If

        Pt(4) = Pt(0)

    Case "@"               '圆孤

        If a1 < 6 Then

            a1 = a1 * 50 + 50                                         'a1+1为半径的圆

            For i = 0 To 71

                Pt(i).x = 350 + a1 * Cos(i * pi / 35): Pt(i).y = 350 + a1 * Sin(i * pi / 35)

            Next i

            n0 = 72

            If a1 <> 50 And a2 = 0 Then a2 = 1

            If a2 > 0 Then

                a1 = a1 - 25 * a2                                      'a2为圆弧宽度

                For i = 0 To 71

                    Pt(i + 72).x = 350 + a1 * Cos((72 - i) * pi / 35): Pt(i + 72).y = 350 + a1 * Sin((72 - i) * pi / 35)

                Next i

                n0 = 144

            End If

            Pt(n0) = Pt(0)

        Else                                                            '否则,a1为圆弧开口方向

        

        a1 = a1 - 6: s = a1

        s1 = s * 90 - 5 * a5 + a2 * 15: s2 = s * 90 - 5 * a5 - a2 * 15 + 360       'a2为圆弧开口大小

        If a2 = 9 Then s1 = s * 90 + 90: s2 = s * 90 - 90 + 360                'a2为圆弧开口大小

        If s1 < 0 Then s1 = s1 + 360

        a3 = 300 - a3 * 33.3                                             'a3为圆弧宽度

        a5 = s * 90 - 5 * a5: a4 = a4 * 30                                 'a4为内圆心偏离程度,a5为内圆心偏离方向

        k = 0

        For i = s1 To s2 Step 5

            Pt(k).x = 350 + 300 * Cos(pi * i / 180): Pt(k).y = 350 - 300 * Sin(pi * i / 180): k = k + 1

        Next i

        xx = 350 + a4 * Cos(a5 * pi / 180): yy = 350 - a4 * Sin(a5 * pi / 180)

        For i = s2 To s1 Step -5

            Pt(k).x = xx + a3 * Cos(pi * i / 180): Pt(k).y = yy - a3 * Sin(pi * i / 180): k = k + 1

        Next i

        Pt(k) = Pt(0)

        If a2 = 9 Then

            Pt(k + 1).x = 350: Pt(k + 1).y = 50

            Pt(k + 2).x = 650: Pt(k + 2).y = 50

            Pt(k + 3).x = 650: Pt(k + 3).y = 350 - a3

            Pt(k + 4).x = 350: Pt(k + 4).y = 350 - a3

            Pt(k + 5).x = 350: Pt(k + 5).y = 50

            Pt(k + 6).x = 350: Pt(k + 6).y = 650

            Pt(k + 7).x = 650: Pt(k + 7).y = 650

            Pt(k + 8).x = 650: Pt(k + 8).y = 350 + a3

            Pt(k + 9).x = 350: Pt(k + 9).y = 350 + a3

            Pt(k + 10).x = 350: Pt(k + 10).y = 650

            If s = 2 Or s = 1 Then Pt(k + 2).x = 50: Pt(k + 3).x = 50: Pt(k + 7).x = 50: Pt(k + 8).x = 50

            If s = 1 Or s = 3 Then

                For i = k + 1 To k + 10: yy = Pt(i).y: Pt(i).y = Pt(i).x: Pt(i).x = yy: Next i

            End If

            Pt(k + 11) = Pt(0)

        End If

       

        End If

    Case "&"               '螺旋形

        n1 = 0: a4 = -1

        If a1 = 1 Then n1 = 15: a4 = 1                            'a1=2时顺时针方向,a1=1时逆时针方向,a1=0时无中心圆点

        If a1 = 2 Then a4 = -1: n1 = 15

        If a1 < 3 Then a1 = 30                                  'a1为角数,小于3为旋弧

        a2 = a2 * 15                                            'a2为旋线宽和旋线隙

        a3 = a3 * pi / 4                                        'a3*45为整体顺转角度

        aa = 2 * pi / a1

        nn = n1 + Int(a1 * 125 / a2): If nn > 138 Then nn = 138

        If n1 = 15 Then

            a5 = a2

            For i = 0 To n1

                Pt(i).x = 350 + a4 * a5 * Cos((15 + i) * aa + a3): Pt(i).y = 350 - a5 * Sin((15 + i) * aa + a3)

            Next i

        Else

            a5 = a2

        End If

            For i = 0 To nn - n1

                Pt(i + n1).x = 350 + a4 * a5 * Cos(i * aa + a3): Pt(i + n1).y = 350 - a5 * Sin(i * aa + a3)

                a5 = a5 + 2 * a2 / a1

                If a5 > 300 Then nn = i + n1: Exit For

            Next i

            a5 = a5 - a2

            For i = nn - n1 To n1 Step -1

                a5 = a5 - 2 * a2 / a1

                Pt(2 * nn - n1 - i + 1).x = 350 + a4 * a5 * Cos(i * aa + a3): Pt(2 * nn - n1 - i + 1).y = 350 - a5 * Sin(i * aa + a3)

            Next i

        If n1 = 0 Then Pt(2 * (nn - n1) + 2) = Pt(n1)

    Case "$"               '波形

        If a1 = 0 Then a1 = 1

        If a2 = 0 Then a2 = 9

        If a3 = 0 Then a3 = 1

        a2 = a2 * 30                                                   'a1为波数,a2为波幅

        a3 = a3 * 30                                                   'a3为弧线宽度,a4不为0,波向垂直

        aa = pi * a1 / 60

        If a4 = 0 Then

            For i = 0 To 120: Pt(i).x = 5 * i: Pt(i).y = 350 - a2 * Sin(i * aa) - a3: Next i

            For i = 121 To 241: Pt(i).x = Pt(241 - i).x: Pt(i).y = Pt(241 - i).y + 2 * a3: Next i

        Else

            For i = 0 To 120: Pt(i).y = 5 * i: Pt(i).x = 350 - a2 * Sin(i * aa) - a3: Next i

            For i = 121 To 241: Pt(i).y = Pt(241 - i).y: Pt(i).x = Pt(241 - i).x + 2 * a3: Next i

        End If

        Pt(242) = Pt(0)

    Case "#"               '星形

        a1 = a1 + 3                           'a1+3为多角形的角数

        a2 = a2                              'a2-1为多角形的两直线相连角之间的角数

        a4 = a4 * 15 * pi / 180

        If a3 = 0 Then

            a2 = a2 * 30                      'a30时,a2为星形的内圆大小。非0时,a2-1为多角形的两直线相连角之间的角数

            For i = 0 To a1

                a5 = a4 + pi / 2 + i * 2 * pi / a1

                Pt(2 * i).x = 350 + 300 * Cos(a5): Pt(2 * i).y = 350 - 300 * Sin(a5)

                a5 = a5 + pi / a1

                Pt(2 * i + 1).x = 350 + a2 * Cos(a5): Pt(2 * i + 1).y = 350 - a2 * Sin(a5)

            Next i

            Pt(2 * i) = Pt(0)

        Else

            If a1 = 3 Then

                aa = 360: a3 = aa - a3 * 40

            Else

                aa = 300: a3 = aa - a3 * 33.333333                                     'a3为多角形的两角连线宽度

            End If

            k = 0: a5 = a1 / a2: If a5 - Int(a5) > 0 Then a5 = 1 Else a5 = a2

            For k1 = 0 To a5 - 1

                a6 = a4 + pi / 2 + k1 * 2 * pi / a1

                For i = 0 To a1 / a5

                    Pt(k).x = 350 + aa * Cos(a6): Pt(k).y = 350 - aa * Sin(a6): k = k + 1

                    a6 = a6 + 2 * pi * a2 / a1

                Next i

                a6 = a6 - 2 * pi * a2 / a1

                For i = a1 / a5 To 0 Step -1

                    Pt(k).x = 350 + a3 * Cos(a6): Pt(k).y = 350 - a3 * Sin(a6): k = k + 1

                    a6 = a6 - 2 * pi * a2 / a1

                Next i

                Pt(k) = Pt(k1 * 2 * (1 + a1 / a5) + k1): k = k + 1

            Next k1

            For k1 = a5 - 1 To 0 Step -1: Pt(k) = Pt(k1 * 2 * (1 + a1 / a5) + k1): k = k + 1: Next k1

        End If

    Case "%"    '不定形。由%后第二个数开始的10个数串0123456789指定的点组成封闭曲线。0246813579分别成左右两曲线。

               '而第一个数a1指定曲线的特性:奇偶定方向垂直或水平,等于452367分别为左,右,两边是折线(不平滑)

            For i = 80 To 100: Pt(i).x = 650: Pt(100 + i).x = 50: Next i

            For i = 0 To 80: Pt(i).x = 50 + i * 7.5: Pt(180 - i).x = 50 + i * 7.5: Next i

            For i = 0 To 4: