comparison weather.tcl @ 437:e28c3347a948

Backed out changeset 3c816fdc302f "great circle distance", for now.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 09 Jan 2017 09:23:05 +0200
parents 3c816fdc302f
children d4f4a9dfb34f
comparison
equal deleted inserted replaced
436:3c816fdc302f 437:e28c3347a948
325 weather_usage $upublic $unick $uchan $weather_msg_usage_nearest 325 weather_usage $upublic $unick $uchan $weather_msg_usage_nearest
326 return 0 326 return 0
327 } 327 }
328 328
329 # Check argument types 329 # Check argument types
330 set pt1_lat [lindex $nlist 0] 330 set d_lat [lindex $nlist 0]
331 set pt1_lng [lindex $nlist 1] 331 set d_lng [lindex $nlist 1]
332 if {![string is double -strict $pt1_lat] || ![string is double -strict $pt1_lng]} { 332 if {![string is double -strict $d_lat] || ![string is double -strict $d_lng]} {
333 weather_msg $upublic $unick $uchan $weather_msg_usage_nearest_invalid 333 weather_msg $upublic $unick $uchan $weather_msg_usage_nearest_invalid
334 return 0 334 return 0
335 } 335 }
336 336
337 # Calculate distances between given coordinates for each location 337 # Calculate distances between given coordinates for each location
338 set result {} 338 set result {}
339 foreach {ukey uvalue} [array get weather_data] { 339 foreach {ukey uvalue} [array get weather_data] {
340 if {![string match "w_*" $ukey]} { 340 if {![string match "w_*" $ukey]} {
341 set pt2_lat [lindex $uvalue 2] 341 set delta_lat [expr {$d_lat - [lindex $uvalue 2]}]
342 set pt2_lng [lindex $uvalue 3] 342 set delta_lng [expr {$d_lng - [lindex $uvalue 3]}]
343 343 set dist [expr { sqrt($delta_lat * $delta_lat + $delta_lng * $delta_lng) }]
344 # Calculate "great circle angle" of two lat/long coordinate pairs
345 # https://en.wikipedia.org/wiki/Great-circle_distance
346 #
347 # The result then can be used to calculate approximate distance
348 # between the points when radius of the sphere "R" is known.
349 set d_lng [expr { $pt2_lng - $pt1_lng }]
350 set c_lat1 [expr { cos($pt1_lat) }]
351 set c_lat2 [expr { cos($pt2_lat) }]
352 set s_lat1 [expr { sin($pt1_lat) }]
353 set s_lat2 [expr { sin($pt2_lat) }]
354
355 set f1 [expr { $c_lat2 * sin($d_lng) }]
356 set f2 [expr { $c_lat2 * cos($d_lng) }]
357 set f3 [expr { $c_lat1 * $s_lat2 - $s_lat1 * $f2 }]
358 set c_ang [expr { atan2(sqrt($f1 * $f1 + $f3 * $f3), $s_lat1 * $s_lat2 + $c_lat1 * $f2) }]
359
360 # Calculate distance based on Earth radius approximation in km * 1000m
361 set dist [expr { 6371.439 * 1000.0 * $c_ang }]
362 lappend result [list $ukey $dist] 344 lappend result [list $ukey $dist]
363 } 345 }
364 } 346 }
365 347
366 # Sort the list by distance 348 # Sort the list by distance
372 lappend uresult [weather_get_str $weather_data([lindex $uval 0]) $weather_msg_list_nearest] 354 lappend uresult [weather_get_str $weather_data([lindex $uval 0]) $weather_msg_list_nearest]
373 } 355 }
374 356
375 # Print out the result 357 # Print out the result
376 set res [join $uresult " ; "] 358 set res [join $uresult " ; "]
377 weather_msg $upublic $unick $uchan $weather_msg_nearest_stations [list $pt1_lat $pt1_lng $res] 359 weather_msg $upublic $unick $uchan $weather_msg_nearest_stations [list $d_lat $d_lng $res]
378 return 0 360 return 0
379 } elseif {$rarg == "vakio" || $rarg == "default" || $rarg == "vakiot" || $rarg == "defaults"} { 361 } elseif {$rarg == "vakio" || $rarg == "default" || $rarg == "vakiot" || $rarg == "defaults"} {
380 # List or set the default weather station name patterns for this user 362 # List or set the default weather station name patterns for this user
381 363
382 # Access check 364 # Access check