Mercurial > hg > egg-tcls
diff weather.tcl @ 430:8efbb045d44d
weather: Implement searching for nearest of measurement stations based on given lat/long coordinates.
The distance calculation is naive pythagoraean one, should be changed to "Great circle distance"
https://en.wikipedia.org/wiki/Great-circle_distance. (C implementation already done, just needs TCL-ization.)
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 08 Jan 2017 05:08:38 +0200 |
parents | 1ada0cb9bdd9 |
children | 3c816fdc302f |
line wrap: on
line diff
--- a/weather.tcl Sun Jan 08 04:56:54 2017 +0200 +++ b/weather.tcl Sun Jan 08 05:08:38 2017 +0200 @@ -286,7 +286,8 @@ global weather_msg_aliased weather_msg_unaliased weather_msg_no_access global weather_msg_def_set weather_msg_def_not_set weather_msg_aliases global weather_msg_usage_stations weather_msg_stations weather_msg_list_station - global weather_msg_result + global weather_msg_list_nearest weather_msg_usage_nearest weather_msg_usage_nearest_invalid + global weather_msg_nearest_stations weather_msg_result # Check and handle arguments set rarglist [::textutil::split::splitx $uargs {\s+}] @@ -316,6 +317,47 @@ set res [join $result " ; "] weather_msg $upublic $unick $uchan $weather_msg_stations [list $res] return 0 + } elseif {$rarg == "lahin" || $rarg == "lähin" || $rarg == "closest" || $rarg == "nearest"} { + # List stations nearest to given coordinates + set qlist [::textutil::split::splitx [join [lrange $rarglist 1 end] " "] {\s*,\s*}] + set nlist [lsearch -all -inline -not -exact $qlist ""] + if {[llength $nlist] < 2} { + weather_usage $upublic $unick $uchan $weather_msg_usage_nearest + return 0 + } + + # Check argument types + set d_lat [lindex $nlist 0] + set d_lng [lindex $nlist 1] + if {![string is double -strict $d_lat] || ![string is double -strict $d_lng]} { + weather_msg $upublic $unick $uchan $weather_msg_usage_nearest_invalid + return 0 + } + + # Calculate distances between given coordinates for each location + set result {} + foreach {ukey uvalue} [array get weather_data] { + if {![string match "w_*" $ukey]} { + set delta_lat [expr {$d_lat - [lindex $uvalue 2]}] + set delta_lng [expr {$d_lng - [lindex $uvalue 3]}] + set dist [expr { sqrt($delta_lat * $delta_lat + $delta_lng * $delta_lng) }] + lappend result [list $ukey $dist] + } + } + + # Sort the list by distance + set usorted [lsort -real -index 1 $result] + + # Create a result list for few best/first matches + set uresult {} + foreach {uval} [lrange $usorted 0 2] { + lappend uresult [weather_get_str $weather_data([lindex $uval 0]) $weather_msg_list_nearest] + } + + # Print out the result + set res [join $uresult " ; "] + weather_msg $upublic $unick $uchan $weather_msg_nearest_stations [list $d_lat $d_lng $res] + return 0 } elseif {$rarg == "vakio" || $rarg == "default" || $rarg == "vakiot" || $rarg == "defaults"} { # List or set the default weather station name patterns for this user