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