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