1 | <?php |
---|
2 | |
---|
3 | class labelmanager |
---|
4 | { |
---|
5 | function labelmanager() |
---|
6 | { |
---|
7 | $this->labels = array(); |
---|
8 | } |
---|
9 | |
---|
10 | // x,y,text,size,font,color,type |
---|
11 | function add($x, $y, $text, $size, $font, $color, $type) |
---|
12 | { |
---|
13 | $label = array('x' => $x, 'y' => $y, 'text' => $text, 'size' => $size, |
---|
14 | 'font' => $font, 'color' => $color, 'type' => $type); |
---|
15 | $this->labels[] = $label; |
---|
16 | } |
---|
17 | |
---|
18 | function resort(&$image) |
---|
19 | { |
---|
20 | // calculate the ideal position for each label |
---|
21 | foreach ($this->labels as $index => $label) |
---|
22 | { |
---|
23 | $bbox = imageftbbox($label['size'], 0, $label['font'], $label['text']); |
---|
24 | $width = abs($bbox[4] - $bbox[0]); |
---|
25 | $height = abs($bbox[5] - $bbox[1]); |
---|
26 | $this->labels[$index]['nx'] = $this->labels[$index]['x'] = $label['x']-$width/2; |
---|
27 | $this->labels[$index]['ny'] = $this->labels[$index]['y'] = $label['y']+$height/2; |
---|
28 | $this->labels[$index]['box'] = $bbox; |
---|
29 | $this->labels[$index]['width'] = $width; |
---|
30 | $this->labels[$index]['height'] = $height; |
---|
31 | } |
---|
32 | |
---|
33 | $this->calcIntersects(); |
---|
34 | for ($i=0; $i<100; $i++) |
---|
35 | { |
---|
36 | foreach ($this->intersects as $index => $sections) |
---|
37 | { |
---|
38 | foreach ($sections as $section) |
---|
39 | { |
---|
40 | $vector = $this->getDirection($index, $section); |
---|
41 | |
---|
42 | $intx = $vector[0]; |
---|
43 | $inty = $vector[1]; |
---|
44 | |
---|
45 | // if the original point is not inside the new label - limit |
---|
46 | if (!$this->pointInLabel($intx+$this->labels[$section]['nx'], $inty+$this->labels[$section]['ny'], $this->labels[$section])) |
---|
47 | { |
---|
48 | $minx = $this->labels[$section]['x']; |
---|
49 | $miny = $this->labels[$section]['y']-$this->labels[$section]['height']; |
---|
50 | // no label leaves the area! |
---|
51 | $minx = max(0, $minx); |
---|
52 | $miny = max($this->labels[$section]['height'], $miny); |
---|
53 | |
---|
54 | $maxx = $this->labels[$section]['x']+$this->labels[$section]['width']; |
---|
55 | $maxy = $this->labels[$section]['y'];; |
---|
56 | |
---|
57 | $intx = min(max($intx+$this->labels[$section]['nx'], $minx), $maxx)-$this->labels[$section]['nx']; |
---|
58 | $inty = min(max($inty+$this->labels[$section]['ny'], $miny), $maxy)-$this->labels[$section]['ny']; |
---|
59 | } |
---|
60 | |
---|
61 | $this->labels[$section]['nx'] += $intx; |
---|
62 | $this->labels[$section]['ny'] += $inty; |
---|
63 | } |
---|
64 | } |
---|
65 | |
---|
66 | $this->calcIntersects(); |
---|
67 | } |
---|
68 | } |
---|
69 | |
---|
70 | // return the best direction to move tag $i2 |
---|
71 | function getDirection($i1, $i2) |
---|
72 | { |
---|
73 | $x = $this->labels[$i2]['nx'] - $this->labels[$i1]['nx']; |
---|
74 | $y = $this->labels[$i2]['ny'] - $this->labels[$i1]['ny']; |
---|
75 | |
---|
76 | if ($x == 0) |
---|
77 | { |
---|
78 | $divisor = $y; |
---|
79 | } |
---|
80 | elseif ($y == 0) |
---|
81 | { |
---|
82 | $divisor = $x; |
---|
83 | } |
---|
84 | else |
---|
85 | { |
---|
86 | $divisor = max(abs($x), abs($y)); |
---|
87 | } |
---|
88 | if ($divisor != 0) |
---|
89 | { |
---|
90 | $x /= $divisor; |
---|
91 | $y /= $divisor; |
---|
92 | } |
---|
93 | return array($x, $y); |
---|
94 | } |
---|
95 | |
---|
96 | function pointInLabel($x, $y, $label) |
---|
97 | { |
---|
98 | return (($label['width'] >= abs($x - $label['x'])) |
---|
99 | && ($label['height'] >= abs($y - $label['y']))); |
---|
100 | } |
---|
101 | |
---|
102 | function calcIntersects() |
---|
103 | { |
---|
104 | $this->intersects = array(); |
---|
105 | foreach ($this->labels as $index => $label) |
---|
106 | { |
---|
107 | foreach ($this->labels as $index2 => $label2) |
---|
108 | { |
---|
109 | if ($index != $index2 && $this->canIntersect($label, $label2)) |
---|
110 | { |
---|
111 | $this->intersects[$index][] = $index2; |
---|
112 | } |
---|
113 | } |
---|
114 | } |
---|
115 | } |
---|
116 | |
---|
117 | |
---|
118 | function sortHelper($a, $b) |
---|
119 | { |
---|
120 | return count($this->intersects[$b]) - count($this->intersects[$a]); |
---|
121 | } |
---|
122 | |
---|
123 | function canIntersect($label1, $label2, $debug = false) |
---|
124 | { |
---|
125 | $xmatch = $ymatch = false; |
---|
126 | if ($label2['nx'] > $label1['nx']) |
---|
127 | { |
---|
128 | $l1x = $label1['nx']+$label1['width']+4; |
---|
129 | $l2x = $label2['nx']; |
---|
130 | if ($l1x >= $l2x) |
---|
131 | { |
---|
132 | $xmatch = true; |
---|
133 | } |
---|
134 | } |
---|
135 | else |
---|
136 | { |
---|
137 | $l1x = $label1['nx']; |
---|
138 | $l2x = $label2['nx']+$label2['width']+4; |
---|
139 | if ($l2x >= $l1x) |
---|
140 | { |
---|
141 | $xmatch = true; |
---|
142 | } |
---|
143 | } |
---|
144 | if ($label2['ny'] > $label1['ny']) |
---|
145 | { |
---|
146 | $l1y = $label1['ny']; |
---|
147 | $l2y = $label2['ny']-$label2['height']-2; |
---|
148 | if ($l1y >= $l2y) |
---|
149 | { |
---|
150 | $ymatch = true; |
---|
151 | } |
---|
152 | } |
---|
153 | else |
---|
154 | { |
---|
155 | $l1y = $label1['ny']-$label1['height']-2; |
---|
156 | $l2y = $label2['ny']; |
---|
157 | if ($l2y >= $l1y) |
---|
158 | { |
---|
159 | $ymatch = true; |
---|
160 | } |
---|
161 | } |
---|
162 | if ($debug) |
---|
163 | { |
---|
164 | echo 'xmatch: '.(int)$xmatch.")\n"; |
---|
165 | echo 'ymatch: '.(int)$ymatch.")\n"; |
---|
166 | } |
---|
167 | return ($xmatch && $ymatch); |
---|
168 | } |
---|
169 | |
---|
170 | function draw(&$image) |
---|
171 | { |
---|
172 | $this->resort($image); |
---|
173 | $black = imagecolorallocate($image, 0, 0, 0); |
---|
174 | |
---|
175 | foreach ($this->labels as $index => $label) |
---|
176 | { |
---|
177 | $this->labels[$index]['x'] = $label['nx']; |
---|
178 | $this->labels[$index]['y'] = $label['ny']; |
---|
179 | } |
---|
180 | |
---|
181 | foreach ($this->labels as $label) |
---|
182 | { |
---|
183 | if ($label['type'] == 'region') |
---|
184 | { |
---|
185 | imagefttext($image, $label['size'], 0, $label['x'], $label['y'], $label['color'], $label['font'], $label['text']); |
---|
186 | } |
---|
187 | elseif ($label['type'] == 'alliance') |
---|
188 | { |
---|
189 | imagefttext($image, $label['size'], 0, $label['x']-1, $label['y'], $black, $label['font'], $label['text']); |
---|
190 | imagefttext($image, $label['size'], 0, $label['x']+1, $label['y'], $black, $label['font'], $label['text']); |
---|
191 | imagefttext($image, $label['size'], 0, $label['x'], $label['y']-1, $black, $label['font'], $label['text']); |
---|
192 | imagefttext($image, $label['size'], 0, $label['x'], $label['y']+1, $black, $label['font'], $label['text']); |
---|
193 | |
---|
194 | imagefttext($image, $label['size'], 0, $label['x'], $label['y'], $label['color'], $label['font'], $label['text']); |
---|
195 | } |
---|
196 | } |
---|
197 | } |
---|
198 | } |
---|
199 | ?> |
---|