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