Mercurial > hg > egg-tcls
changeset 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 | 5763716060a0 |
files | config.weather.example weather.tcl |
diffstat | 2 files changed, 50 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/config.weather.example Sun Jan 08 04:56:54 2017 +0200 +++ b/config.weather.example Sun Jan 08 05:08:38 2017 +0200 @@ -35,7 +35,7 @@ ### ### Messages ### -set weather_msg_list_station [list "\002@station@\002 ( http://www.google.fi/maps/@@c_lat@,@c_lng@,15z )"] +set weather_msg_list_station [list "\002@station@\002 ( http://www.google.fi/maps/@@c_lat@,@c_lng@,18z )"] set weather_msg_result [list "\002@station@\002, mitattu klo @ctime@: \002@temp@°C\002"] @@ -51,6 +51,12 @@ set weather_msg_usage_prefix_1 "Käyttö: !sää " set weather_msg_usage_prefix_2 " !sää " +set weather_msg_list_nearest $weather_msg_list_station +set weather_msg_usage_nearest "lähin <lat>\[, \]<long> -- näyttää annettuja koordinaatteja lähimpänä olevat mittausasemat" +set weather_msg_usage_nearest_invalid "lähin <lat>\[, \]<long> -- näyttää annettuja koordinaatteja lähimpänä olevat mittausasemat" +set weather_msg_nearest_stations "Lähimmät mittausasemat (%1, %2): %3" + + set weather_msg_usage_def_set "vakio <paikka>\[;<paikka2>\] -- asettaa vakiohavaintoaseman\nvakio -- näyttää nykyisen" set weather_msg_usage_alias "alias <alias> = <nimi> (Lisää alias-nimen, esim. alias perse = turku)" set weather_msg_usage_unalias "unalias <alias> (Poistaa aliaksen)"
--- 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