i
[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         link = char.ids_represent if char.ids_represent
39         link = char.ids_link if char.ids_link
40         return if link.nil?
41         @h[ch] << link #親字に追加する。
42         @list << link
43         return
44       end
45       
46       ids.each_char {|idsch|
47         idschar = idsch.char
48         next if idschar.is_ids?
49         @h[ch] << idsch #親字に追加する。
50         @list << idsch
51         make_network_one(idsch) #再帰する。
52       }
53       @done[ch] = true
54     end
55     
56     def nodes_and_edges() #これを二つのarrayで返す
57       nodear = []
58       nodeh  = Hash.new
59       @list.sort.uniq.each_with_index {|ch, index|
60         nodear[index] = ch
61         nodeh[ch] = index
62       }
63       edgear = []
64       @h.each {|ch, ar|
65         ar.each {|idsch|
66           edgear << [nodeh[ch], nodeh[idsch]]
67         }
68       }
69       return nodear, edgear
70     end
71
72     def out(filename)
73       open(filename, "w"){|out| out.print to_s }
74     end
75
76     def to_s() @formatter.to_s; end
77   end
78
79   class GraphvizFormatter # Graphviz関係
80     def initialize(network)
81       @network = network
82     end
83
84     def to_s() #Graphvizのフォーマット、dotフォーマットに変換する。
85       page = DotPage.new
86       page.size = "5.5, 5.5"
87       #page.pack = "true"
88       #page.epsilon = 0.001
89       #page.epsilon = 0.01
90       #page.overlap = false
91       #page.overlap = scale
92       #page.spline = true
93
94       #p @network.list
95       @network.list.sort.uniq.each {|ch|
96         char = ch.char
97         node = DotNode.new(char.to_i)
98         node.label = char.map_ucs_er #node.label = char.to_utf8
99         node.fontsize = (node.label =~ /^&#/) ? 12 : 6
100         #node.fontsize = (node.label =~ /^&#/) ? 24 : 6
101         node.shape = "plaintext"
102         node.fontname = "MS-Mincho" #呪われてるがしかたがない
103         #node.fontname = "Arial-Unicode-MS" #ダメ
104         page.add_node(node)
105       }
106
107       @network.h.each {|ch, ar|
108         char = ch.char
109         ar.each {|idsch|
110           idschar = idsch.char
111           edge = DotEdge.new(char.to_i, idschar.to_i)
112           #edge.len = 4
113           #edge.len = 2
114           #edge.color = "gray"
115           edge.color = "lightgray"
116           page.add_edge(edge)
117         }
118       }
119       return page.to_s
120     end
121   end
122
123   class XSpringiesFormatter
124     def initialize(network)
125       @network = network
126     end
127
128     def to_s # #1.0 *** XSpringies data file
129       str = ""
130       @network.list.sort.uniq.each {|ch|
131         char = ch.char
132         num = char.to_i
133         label = char.map_ucs_er
134         str << "mass #{num}\n"
135       }
136       @network.h.each {|ch, ar|
137         char = ch.char
138         ar.each {|idsch|
139           idschar = idsch.char
140           from = char.to_i
141           to = idschar.to_i
142           str << "spng #{from} #{to}\n"
143         }
144       }
145       str
146     end
147
148   end
149 end