6fa4eedd28d0f54a12e23536f62084c9a52616c1
[chise/ruby.git] / src / network.rb
1 #!/usr/bin/env ruby
2 # calc KanjiNetwork by eto 2003-0305
3
4 require 'chise'
5 require 'kanjilist'
6 require 'defkanji'
7 require 'graphviz'
8
9 module CHISE
10   class KanjiNetwork #======================================================================漢字間のネットワークを計算する。
11     def initialize()
12       reset()
13       @formatter = GraphvizFormatter.new(self)
14       # @formatter = XSpringiesFormatter.new(self)
15     end
16     attr_reader :h, :list
17     def reset
18       @h = Hash.new
19       @done = Hash.new
20       @list = []
21     end
22     def make_network(list) #@h, @listに結果を入れていく。
23       list.each_char {|ch|
24         make_network_one(ch)
25       }
26     end
27     
28     def make_network_one(ch) #実質的にこれが本体。再帰で呼ばれる。
29       return if @done[ch]
30       
31       @h[ch] = []
32       @list << ch #登場文字リストに追加
33       
34       char = ch.char
35       ids = char.decompose
36       if ids.char_length == 1 #分割できない文字は、リンクを探す。
37         link = char.ids_represent if char.ids_represent
38         link = char.ids_link if char.ids_link
39         return if link.nil?
40         @h[ch] << link #親字に追加する。
41         @list << link
42         return
43       end
44       
45       ids.each_char {|idsch|
46         idschar = idsch.char
47         next if idschar.is_ids?
48         @h[ch] << idsch #親字に追加する。
49         @list << idsch
50         make_network_one(idsch) #再帰する。
51       }
52       @done[ch] = true
53     end
54     
55     def nodes_and_edges() #これを二つのarrayで返す
56       nodear = []
57       nodeh  = Hash.new
58       @list.sort.uniq.each_with_index {|ch, index|
59         nodear[index] = ch
60         nodeh[ch] = index
61       }
62       edgear = []
63       @h.each {|ch, ar|
64         ar.each {|idsch|
65           edgear << [nodeh[ch], nodeh[idsch]]
66         }
67       }
68       return nodear, edgear
69     end
70
71     def out(filename)
72       open(filename, "w"){|out| out.print to_s }
73     end
74     def to_s() @formatter.to_s; end
75   end
76
77   class GraphvizFormatter #====================================================================== Graphviz関係
78     def initialize(network)
79       @network = network
80     end
81     def to_s() #Graphvizのフォーマット、dotフォーマットに変換する。
82       page = DotPage.new
83       page.size = "5.5, 5.5"
84       #page.pack = "true"
85       #page.epsilon = 0.001
86       #page.epsilon = 0.01
87       #page.overlap = false
88       #page.overlap = scale
89       #page.spline = true
90
91       #p @network.list
92       @network.list.sort.uniq.each {|ch|
93         char = ch.char
94         node = DotNode.new(char.to_i)
95         node.label = char.map_ucs_er #node.label = char.to_utf8
96         node.fontsize = (node.label =~ /^&#/) ? 12 : 6
97         #node.fontsize = (node.label =~ /^&#/) ? 24 : 6
98         node.shape = "plaintext"
99         node.fontname = "MS-Mincho" #呪われてるがしかたがない
100         #node.fontname = "Arial-Unicode-MS" #ダメ
101         page.add_node(node)
102       }
103
104       @network.h.each {|ch, ar|
105         char = ch.char
106         ar.each {|idsch|
107           idschar = idsch.char
108           edge = DotEdge.new(char.to_i, idschar.to_i)
109           #edge.len = 4
110           #edge.len = 2
111           #edge.color = "gray"
112           edge.color = "lightgray"
113           page.add_edge(edge)
114         }
115       }
116       return page.to_s
117     end
118   end
119
120   class XSpringiesFormatter #======================================================================
121     def initialize(network)
122       @network = network
123     end
124     def to_s # #1.0 *** XSpringies data file
125       str = ""
126       @network.list.sort.uniq.each {|ch|
127         char = ch.char
128         num = char.to_i
129         label = char.map_ucs_er
130         str << "mass #{num}\n"
131       }
132       @network.h.each {|ch, ar|
133         char = ch.char
134         ar.each {|idsch|
135           idschar = idsch.char
136           from = char.to_i
137           to = idschar.to_i
138           str << "spng #{from} #{to}\n"
139         }
140       }
141       str
142     end
143   end
144 end
145
146 #----------------------------------------------------------------------end.