i
[chise/ruby.git] / chise / network.rb
1 # Copyright (C) 2002-2004 Kouichirou Eto, All rights reserved.
2
3 $LOAD_PATH << "../../lib" if $0 == __FILE__
4 require "chise"
5 include CHISE
6 require "chise/kanjilist"
7 require "chise/defkanji"
8 require "chise/graphviz"
9
10 module CHISE
11   class KanjiNetwork #=========================漢字間のネットワークを計算する。
12     def initialize()
13       reset()
14       @formatter = GraphvizFormatter.new(self)
15       # @formatter = XSpringiesFormatter.new(self)
16     end
17     attr_reader :h, :list
18     def reset
19       @h = Hash.new
20       @done = Hash.new
21       @list = []
22     end
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     def to_s() @formatter.to_s; end
76   end
77
78   class GraphvizFormatter #======================================== Graphviz関係
79     def initialize(network)
80       @network = network
81     end
82     def to_s() #Graphvizのフォーマット、dotフォーマットに変換する。
83       page = DotPage.new
84       page.size = "5.5, 5.5"
85       #page.pack = "true"
86       #page.epsilon = 0.001
87       #page.epsilon = 0.01
88       #page.overlap = false
89       #page.overlap = scale
90       #page.spline = true
91
92       #p @network.list
93       @network.list.sort.uniq.each {|ch|
94         char = ch.char
95         node = DotNode.new(char.to_i)
96         node.label = char.map_ucs_er #node.label = char.to_utf8
97         node.fontsize = (node.label =~ /^&#/) ? 12 : 6
98         #node.fontsize = (node.label =~ /^&#/) ? 24 : 6
99         node.shape = "plaintext"
100         node.fontname = "MS-Mincho" #呪われてるがしかたがない
101         #node.fontname = "Arial-Unicode-MS" #ダメ
102         page.add_node(node)
103       }
104
105       @network.h.each {|ch, ar|
106         char = ch.char
107         ar.each {|idsch|
108           idschar = idsch.char
109           edge = DotEdge.new(char.to_i, idschar.to_i)
110           #edge.len = 4
111           #edge.len = 2
112           #edge.color = "gray"
113           edge.color = "lightgray"
114           page.add_edge(edge)
115         }
116       }
117       return page.to_s
118     end
119   end
120
121   class XSpringiesFormatter #=================================================
122     def initialize(network)
123       @network = network
124     end
125
126     def to_s # #1.0 *** XSpringies data file
127       str = ""
128       @network.list.sort.uniq.each {|ch|
129         char = ch.char
130         num = char.to_i
131         label = char.map_ucs_er
132         str << "mass #{num}\n"
133       }
134       @network.h.each {|ch, ar|
135         char = ch.char
136         ar.each {|idsch|
137           idschar = idsch.char
138           from = char.to_i
139           to = idschar.to_i
140           str << "spng #{from} #{to}\n"
141         }
142       }
143       str
144     end
145
146   end
147 end