tkmap.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006 package require Tcl 8.4
00007 package require Tk 8.4
00008 package require mapproj 1.0
00009
00010
00011
00012
00013
00014
00015 namespace ncar780_0 {
00016 variable libdir [file dirname [info script]]
00017 variable mapFile [file join $libdir ncar780.txt]
00018 namespace export readMap cancelReadMap
00019 }
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 ret ncar780_0::readMap (type lineCallback , type doneCallback) {
00064 variable mapFile
00065 variable mapReaders
00066 if {![info exists mapReaders]} {
00067 set mapReaders 0
00068 } else {
00069 incr mapReaders
00070 }
00071 upvar #0 [namespace current]::mapReader$mapReaders state
00072 set state(lineCallback) $lineCallback
00073 set state(doneCallback) $doneCallback
00074 set state(channel) [open $mapFile RDONLY]
00075 readMapGroup $mapReaders
00076 return $mapReaders
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 ret ncar780_0::cancelReadMap (type reader) {
00099 upvar #0 [namespace current]::mapReader$reader state
00100 catch {
00101 after cancel $state(idleHandler)
00102 }
00103 unset [namespace current]::mapReader$reader
00104 return
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 ret ncar780_0::readMapGroup (type reader) {
00129 upvar #0 [namespace current]::mapReader$reader state
00130
00131 set f $state(channel)
00132 for {set i 0} {$i < 10} {incr i} {
00133 set pointList {}
00134 if {[gets $f line] >= 0} {
00135 regexp {^(........)(.*)} $line junk nPoints line
00136 set nPoints [string trim $nPoints]
00137 if {$nPoints < 2} {
00138 close $f
00139 uplevel #0 $state(doneCallback)
00140 unset [namespace current]::mapReader$reader
00141 return
00142 }
00143 regexp {^(........)(.*)} $line junk groupId line
00144 set groupId [string trim $groupId]
00145 regexp {^(........)(.*)} $line junk maxLat line
00146 set maxLat [string trim $maxLat]
00147 regexp {^(........)(.*)} $line junk minLat line
00148 set minLat [string trim $minLat]
00149 regexp {^(........)(.*)} $line junk maxLon line
00150 set maxLon [string trim $maxLon]
00151 regexp {^(........)(.*)} $line junk minLon line
00152 set minLon [string trim $minLon]
00153 set pointList {}
00154 set ptsLeft 0
00155 for {set i 0} {$i < $nPoints} {incr i 2} {
00156 if {$ptsLeft == 0} {
00157 gets $f line
00158 set ptsLeft 5
00159 }
00160 regexp {^(........)(........)(.*)} $line junk lat lon line
00161 lappend pointList [string trim $lon] [string trim $lat]
00162 incr ptsLeft -1
00163 }
00164 uplevel \#0 $state(lineCallback) [list $groupId \
00165 $minLat $minLon $maxLat $maxLon \
00166 $pointList]
00167
00168 } else {
00169 unset [namespace current]::mapReader$reader
00170 close $f
00171 uplevel #0 $doneCallback
00172 return
00173 }
00174 }
00175 set state(idleHandler) [after 2 [namespace code \
00176 [list readMapGroup $reader]]]
00177 return
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 ret plot (type id , type la0 , type lo0 , type la1 , type lo1 , type ptlist) {
00203 variable toProjCmd
00204 set command [list .c create line]
00205 foreach {lo la} $ptlist {
00206 set ok 0
00207 set pcmd $toProjCmd
00208 lappend pcmd $lo $la
00209 foreach {x y} [eval $pcmd] {
00210 set ok 1
00211 }
00212 if {!$ok
00213 || ([info exists lastx] && hypot($x-$lastx, $y-$lasty) > 0.25)} {
00214 if {[llength $command] >= 7} {
00215 if {$id == 0} {
00216 lappend command -fill \#cccccc
00217 } else {
00218 lappend command -fill \#cc0000
00219 }
00220 eval $command
00221 }
00222 set command [list .c create line]
00223 }
00224 if {$ok} {
00225 lappend command [expr {316 + 100 * $x}] \
00226 [expr {316 - 100 * $y}]
00227 set lastx $x
00228 set lasty $y
00229 }
00230 }
00231 if {[llength $command] >= 7} {
00232 if {$id == 0} {
00233 lappend command -fill \#cccccc
00234 } else {
00235 lappend command -fill \#cc0000
00236 }
00237 lappend command -tags id$id
00238 eval $command
00239 }
00240 return
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 ret done () {
00254 variable reader
00255 unset reader
00256 .c configure -scrollregion [.c bbox all]
00257 return
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 ret locate (type w , type x , type y) {
00275 variable lon
00276 variable lat
00277 variable fromProjCmd
00278 set x [$w canvasx $x]
00279 set y [$w canvasy $y]
00280 set x [expr {($x - 316.) / 100.}]
00281 set y [expr {(316. - $y) / 100.}]
00282 set pcmd $fromProjCmd
00283 lappend pcmd $x $y
00284 foreach {lon lat} [eval $pcmd] break
00285 return
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 ret showMap () {
00301 variable showMapScheduled
00302 if {[info exists showMapScheduled]} {
00303 after cancel $showMapScheduled
00304 unset showMapScheduled
00305 }
00306 set showMapScheduled [after 500 showMap2]
00307 return
00308 }
00309 ret showMap2 () {
00310 variable showMapScheduled
00311 if {[info exists showMapScheduled]} {
00312 after cancel $showMapScheduled
00313 unset showMapScheduled
00314 }
00315 variable projection
00316 variable fromProjCmd
00317 variable toProjCmd
00318 variable reader
00319 if {[info exists reader]} {
00320 ncar780_0::cancelReadMap $reader
00321 unset reader
00322 }
00323 .c delete all
00324
00325 foreach {toProjCmd fromProjCmd} [makeProjCmds $projection] break
00326 for {set m -180} {$m <= 180} {incr m 15} {
00327 set plist {}
00328 for {set p -89} {$p <= 89} {incr p} {
00329 lappend plist $m $p
00330 }
00331 plot 0 -90.0 $m 90.0 $m $plist
00332 }
00333 for {set p -75} {$p <= 75} {incr p 15} {
00334 set plist {}
00335 for {set m -180} {$m <= 180} {incr m} {
00336 lappend plist $m $p
00337 }
00338 plot 0 $p -180.0 $p 180.0 $plist
00339 }
00340 set reader [ncar780_0::readMap plot done]
00341 return
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 ret makeProjCmds (type pro , optional comps =1) {
00365 variable phi_0
00366 variable phi_1
00367 variable phi_2
00368 variable lambda_0
00369 set toProjCmd ::mapproj::to$pro
00370 set alist [info args ::mapproj::to$pro]
00371 if {[llength $alist] < 2} {
00372 return -code error "$toProjCmd has too few args"
00373 }
00374 if {[lindex $alist end-1] ne {lambda}
00375 || [lindex $alist end] ne {phi}} {
00376 return -code error "$toProjCmd does not accept lambda and phi"
00377 }
00378 foreach a [lrange $alist 0 end-2] {
00379 switch -exact $a {
00380 phi_0 - phi_1 - phi_2 - lambda_0 {
00381 lappend toProjCmd [set $a]
00382 set have($a) {}
00383 }
00384 default {
00385 return -code error "$toProjCmd accepts an unknown arg $a"
00386 }
00387 }
00388 }
00389 set fromProjCmd ::mapproj::from$pro
00390 set alist [info args ::mapproj::from$pro]
00391 if {[llength $alist] < 2} {
00392 return -code error "$fromProjCmd has too few args"
00393 }
00394 if {[lindex $alist end-1] ne {x}
00395 || [lindex $alist end] ne {y}} {
00396 return -code error "$fromProjCmd does not accept x and y"
00397 }
00398 foreach a [lrange $alist 0 end-2] {
00399 switch -exact $a {
00400 phi_0 - phi_1 - phi_2 - lambda_0 {
00401 lappend fromProjCmd [set $a]
00402 set have($a) {}
00403 }
00404 default {
00405 return -code error "$fromProjCmd accepts an unknown arg $a"
00406 }
00407 }
00408 }
00409 if {$comps} {
00410 foreach item {lambda_0 phi_0 phi_1 phi_2} {
00411 if {[info exists have($item)] && ![winfo ismapped .extras.$item]} {
00412 grid .extras.$item -sticky ew -columnspan 2
00413 } elseif {![info exists have($item)]
00414 && [winfo ismapped .extras.$item]} {
00415 grid forget .extras.$item
00416 }
00417 }
00418 }
00419 return [list $toProjCmd $fromProjCmd]
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 ret isProjection (type pro) {
00433 if {![catch {makeProjCmds $pro 0} r]} {
00434 return 1
00435 } else {
00436 puts $r
00437 return 0
00438 }
00439 }
00440
00441
00442
00443 phi = _0 15.0;
00444 phi = _1 -30.0;
00445 phi = _2 60.0;
00446 lambda = _0 12.0;
00447
00448
00449
00450 canvas .c -width 632 -height 632 -bg white
00451 listbox .projs -height 10 -width 30 -yscrollcommand [list .projsy ]
00452 scrollbar = .projsy -orient vertical -command [list .projs yview]
00453 frame .extras
00454 label .extras.llat -text "Latitude:" -anchor w
00455 entry .extras.elat -width 20 -textvariable lat -state disabled
00456 label .extras.llon -text "Longitude:" -anchor w
00457 entry .extras.elon -width 20 -textvariable lon -state disabled
00458 scale .extras.phi_0 -label "Reference latitude" \
00459 -variable phi_0 -from -90.0 -to 90.0 -length 180 -orient horizontal
00460 scale .extras.lambda_0 -label "Reference longitude" \
00461 -variable lambda_0 -from -180.0 -to 180.0 -length 180 -orient horizontal
00462 scale .extras.phi_1 -label "First standard parallel" \
00463 -variable phi_1 -from -90.0 -to 90.0 -length 180 -orient horizontal
00464 scale .extras.phi_2 -label "Second standard parallel" \
00465 -variable phi_2 -from -90.0 -to 90.0 -length 180 -orient horizontal
00466
00467 grid .extras.llat .extras.elat -sticky nsew
00468 grid .extras.llon .extras.elon -sticky nsew
00469 grid .extras.lambda_0 - -sticky nsew
00470 grid .extras.phi_0 - -sticky nsew
00471 grid .extras.phi_1 - -sticky nsew
00472 grid .extras.phi_2 - -sticky nsew
00473
00474 grid rowconfigure .extras 20 -weight 1
00475
00476 grid .c .projs .projsy -sticky nsew
00477 grid ^ .extras - -sticky nsew
00478
00479 grid rowconfigure . 1 -weight 1
00480 grid columnconfigure . 0 -weight 1
00481
00482 foreach cmd [info commands ::mapproj::to*] {
00483 if {[regexp ^::mapproj::to(.*) $cmd -> pro]
00484 && [namespace origin ::mapproj::from$pro] ne {}
00485 && [isProjection $pro]} {
00486 lappend prolist $pro
00487 }
00488 }
00489
00490 bind .c <1> {locate %W %x %y}
00491 bind .projs <<ListboxSelect>> {
00492 foreach p [.projs curselection] {
00493 projection = [.projs get $p]
00494 }
00495 showMap
00496 }
00497 foreach pro [lsort -dictionary $prolist] {
00498 .projs insert end $pro
00499 }
00500
00501 .projs selection 0
00502 event = generate .projs <<ListboxSelect>>
00503
00504 trace add variable phi_0 write "showMap;\/* "*/
00505 trace add variable phi_1 write "showMap;\/* "*/
00506 trace add variable phi_2 write "showMap;\/* "*/
00507 trace add variable lambda_0 write "showMap;\/* "*/
00508