Added geo.php
[lhc/web/wiklou.git] / tests / geo.php
1 <?
2
3 $a = array (
4 "germany" => "
5 !type[political]:country
6 !name[de]:Deutschland
7 !name[en]:Germany
8 !region[political]:
9 addregs(germany-west,germany-east);
10 include(danube)
11 ",
12
13 "germany-west" => "
14 !type[political]:county
15 !name[de]:Westdeutschland
16 !name[en]:Western Germany
17 !region[political]:
18 polygon(germany-border-north-w,germany-border-ew,germany-border-south-w,germany-border-west-w)
19 ",
20
21 "germany-east" => "
22 !type[political]:county
23 !name[de]:Westdeutschland
24 !name[en]:Western Germany
25 !region[political]:
26 polygon(germany-border-north-e,germany-border-east-e,germany-border-south-e,germany-border-ew)
27 ",
28
29 "germany-border-ew" => "!data:2,2 2,3",
30
31 "germany-border-north-w" => "!data:1,1 1.8,1",
32 "germany-border-south-w" => "!data:1,4 2.2,4",
33 "germany-border-west-w" => "!data:1,1 1,4",
34
35 "germany-border-north-e" => "!data:2,2 3,2",
36 "germany-border-south-e" => "!data:2,3 3,3",
37 "germany-border-east-e" => "!data:3,2 3,3",
38
39 "danube" => "
40 !type:river
41 !region:polyline(danube_germany,danube_austria)
42 " ,
43
44 "danube_germany" =>"!data:1.2,3.5 1.8,2.5 2,2.9" ,
45 "danube_austria" =>"!data:2.2,3.5 2.5,3.2 3,3.7" ,
46
47 ) ;
48
49 # Global functions
50 function geo_get_text ( $id )
51 {
52 global $a ;
53 return $a[$id] ;
54 }
55
56 function data_to_real ( &$x , &$y )
57 {
58 $x = $x * 100 ;
59 $y = $y * 100 ;
60 }
61
62
63 # "geo" class
64 class geo
65 {
66 var $data = array () ;
67 function set_from_text ( $t )
68 {
69 $t = explode ( "\n!" , "\n".$t ) ;
70 $this->data = array () ;
71 foreach ( $t AS $x )
72 {
73 $b = explode ( ":" , $x , 2 ) ;
74 while ( count ( $b ) < 2 ) $b[] = "" ;
75 $key = strtolower ( str_replace ( " " , "" , array_shift ( $b ) ) ) ;
76 $key = str_replace ( "\n" , "" , $key ) ;
77 $value = trim ( str_replace ( "\n" , "" , array_shift ( $b ) ) ) ;
78 $value = explode ( ";" , $value ) ;
79 if ( $key != "" ) $this->data[$key] = $value ;
80 }
81 }
82
83 function set_from_id ( $id )
84 {
85 $this->set_from_text ( geo_get_text ( $id ) ) ;
86 }
87
88 function get_data ()
89 {
90 $ret = array () ;
91 if ( !isset ( $this->data["data"] ) ) return $ret ; # No data in this set
92 $data = $this->data["data"] ;
93 $data = array_shift ( $data ) ;
94 $data = explode ( " " , $data ) ;
95 foreach ( $data AS $a )
96 {
97 $a = explode ( "," , $a ) ;
98 if ( count ( $a ) == 2 )
99 {
100 $x = trim ( array_shift ( $a ) ) ;
101 $y = trim ( array_shift ( $a ) ) ;
102 $ret[] = array ( $x , $y ) ;
103 }
104 }
105 return $ret ;
106 }
107
108 function add_reordered_data ( &$original , &$toadd )
109 {
110 if ( count ( $toadd ) == 0 ) return ; # Nothing to add
111 if ( count ( $original ) == 0 )
112 {
113 $original = $toadd ;
114 return ;
115 }
116
117 $o_last = array_pop ( $original ) ; array_push ( $original , $o_last ) ; # Get last one and restore
118 $t_last = array_pop ( $toadd ) ; array_push ( $toadd , $t_last ) ; # Get last one and restore
119 $t_first = array_shift ( $toadd ) ; array_unshift ( $toadd , $t_first ) ; # Get first one and restore
120
121 $dist_to_first = ( $o_last[0] - $t_first[0] ) * ( $o_last[0] - $t_first[0] ) +
122 ( $o_last[1] - $t_first[1] ) * ( $o_last[1] - $t_first[1] ) ;
123
124 $dist_to_last = ( $o_last[0] - $t_last[0] ) * ( $o_last[0] - $t_last[0] ) +
125 ( $o_last[1] - $t_last[1] ) * ( $o_last[1] - $t_last[1] ) ;
126
127 if ( $dist_to_last < $dist_to_first ) # If the last point of toadd is closer than the fist one,
128 $toadd = array_reverse ( $toadd ) ; # add in other direction
129
130 $original = array_merge ( $original , $toadd ) ;
131 }
132
133 function get_specs ( $base , $modes )
134 {
135 foreach ( $modes AS $x )
136 {
137 if ( isset ( $this->data["{$base}[{$x}]"] ) )
138 return "{$base}[{$x}]" ;
139 }
140 if ( isset ( $this->data[$base] ) )
141 return $base ;
142 return "" ;
143 }
144
145 function get_current_type ( $params ) # params may override native type
146 {
147 $t = $this->get_specs ( "type" , array ( "political" ) ) ;
148 if ( $t != "" ) $t = $this->data[$t][0] ;
149 return $t ;
150 }
151
152 function get_current_style ( $params )
153 {
154 $t = trim ( strtolower ( $this->get_current_type ( $params ) ) ) ;
155 if ( $t == "river" ) $s = "fill:none; stroke:blue; stroke-width:2" ;
156 else $s = "fill:brown; stroke:black; stroke-width:1" ;
157 return "style=\"{$s}\"" ;
158 }
159
160 function draw_line ( $line , $params )
161 {
162 $ret = "" ;
163 $a = explode ( "(" , $line , 2 ) ;
164 while ( count ( $a ) < 2 ) $a[] = "" ;
165 $command = trim ( strtolower ( array_shift ( $a ) ) ) ;
166 $values = trim ( str_replace ( ")" , "" , array_shift ( $a ) ) ) ;
167 # print "Evaluating command {$line}\n" ;
168 if ( $command == "addregs" || $command == "include" )
169 {
170 $values = explode ( "," , $values ) ;
171 foreach ( $values AS $v )
172 {
173 $v = trim ( strtolower ( $v ) ) ;
174 $ng = new geo ;
175 $ng->set_from_id ( $v ) ;
176 $ret .= $ng->draw ( $params ) ;
177 }
178 }
179 else if ( $command == "polygon" || $command == "polyline" )
180 {
181 $data = array () ;
182 $values = explode ( "," , $values ) ;
183 foreach ( $values AS $v )
184 {
185 $v = trim ( strtolower ( $v ) ) ;
186 $ng = new geo ;
187 $ng->set_from_id ( $v ) ;
188 $b = $ng->get_data () ;
189 $this->add_reordered_data ( $data , $b ) ;
190 }
191
192 $style = $this->get_current_style ( $params ) ;
193 if ( $command == "polygon" ) $ret .= "<polygon {$style} points=\"" ;
194 if ( $command == "polyline" ) $ret .= "<polyline {$style} points=\"" ;
195 foreach ( $data AS $a )
196 {
197 $x = $a[0] ;
198 $y = $a[1] ;
199 data_to_real ( $x , $y ) ;
200 $ret .= "{$x},{$y} " ;
201 }
202 $ret = trim ( $ret ) . "\"/>\n" ;
203
204 }
205 return $ret ;
206 }
207
208 function draw ( $params = array() )
209 {
210 $ret = "" ;
211 $match = $this->get_specs ( "region" , array ( "political" ) ) ;
212 if ( $match != "" )
213 {
214 $a = $this->data[$match] ;
215 foreach ( $a AS $line )
216 $ret .= $this->draw_line ( $line , $params ) ;
217 }
218 return $ret ;
219 }
220 }
221
222
223 $g = new geo ;
224 $g->set_from_id ( "germany" ) ;
225
226 $p = array () ;
227 $svg = $g->draw ( $p ) ;
228
229 $styles = "" ;
230 /*
231 $styles = ' <defs>
232 <style type="text/css"><![CDATA[
233 .stuff {fill:none; stroke:blue; stroke-width:2}
234 ]]></style>
235 </defs>
236 ' ;
237 */
238
239 $svg =
240 '<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
241 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/SVG/DTD/svg10.dtd">
242 <svg viewBox="0 0 270 400"
243 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve">
244 '
245 . $styles .
246 ' <g id="mainlayer">
247 '
248 . $svg .
249 '</g>
250 </svg>
251 ' ;
252
253 print $svg ;
254
255 ?>