1 | # -*- mode: tcl; indent-tabs-mode: nil -*- |
---|
2 | # ---------------------------------------------------------------------- |
---|
3 | # VisViewer - |
---|
4 | # |
---|
5 | # This class is the base class for the various visualization viewers |
---|
6 | # that use the nanoserver render farm. |
---|
7 | # |
---|
8 | # ====================================================================== |
---|
9 | # AUTHOR: Michael McLennan, Purdue University |
---|
10 | # Copyright (c) 2004-2012 HUBzero Foundation, LLC |
---|
11 | # |
---|
12 | # See the file "license.terms" for information on usage and |
---|
13 | # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
14 | # ====================================================================== |
---|
15 | |
---|
16 | itcl::class ::Rappture::VisViewer { |
---|
17 | inherit itk::Widget |
---|
18 | |
---|
19 | itk_option define -sendcommand sendCommand SendCommand "" |
---|
20 | itk_option define -receivecommand receiveCommand ReceiveCommand "" |
---|
21 | |
---|
22 | private common _servers ;# array of visualization server lists |
---|
23 | set _servers(nanovis) "localhost:2000" |
---|
24 | set _servers(pymol) "localhost:2020" |
---|
25 | set _servers(vmdmds) "localhost:2018" |
---|
26 | set _servers(vtkvis) "localhost:2010" |
---|
27 | |
---|
28 | private common _done ; # Used to indicate status of send. |
---|
29 | private variable _buffer ; # buffer for incoming/outgoing commands |
---|
30 | private variable _outbuf ; # buffer for outgoing commands |
---|
31 | private variable _blockOnWrite 0; # Should writes to socket block? |
---|
32 | private variable _initialized |
---|
33 | private variable _isOpen 0 |
---|
34 | private variable _afterId -1 |
---|
35 | private variable _icon 0 |
---|
36 | private variable _trace 0 ; # Protocol tracing for console |
---|
37 | private variable _logging 0 ; # Command logging to file |
---|
38 | # Number of milliseconds to wait before idle timeout. If greater than 0, |
---|
39 | # automatically disconnect from the visualization server when idle timeout |
---|
40 | # is reached. |
---|
41 | private variable _idleTimeout 43200000; # 12 hours |
---|
42 | #private variable _idleTimeout 5000; # 5 seconds |
---|
43 | #private variable _idleTimeout 0; # No timeout |
---|
44 | |
---|
45 | protected variable _serverType "???";# Type of server. |
---|
46 | protected variable _sid "" ; # socket connection to server |
---|
47 | protected variable _maxConnects 100 |
---|
48 | protected variable _buffering 0 |
---|
49 | protected variable _cmdSeq 0 ; # Command sequence number |
---|
50 | protected variable _dispatcher ""; # dispatcher for !events |
---|
51 | protected variable _hosts "" ; # list of hosts for server |
---|
52 | protected variable _parser "" ; # interpreter for incoming commands |
---|
53 | protected variable _image |
---|
54 | protected variable _hostname |
---|
55 | protected variable _numConnectTries 0 |
---|
56 | protected variable _debugConsole 0 |
---|
57 | protected variable _reportClientInfo 1 |
---|
58 | # Number of milliscends to wait for server reply before displaying wait |
---|
59 | # dialog. If set to 0, dialog is never displayed. |
---|
60 | protected variable _waitTimeout 0 |
---|
61 | |
---|
62 | constructor { servers args } { |
---|
63 | # defined below |
---|
64 | } |
---|
65 | destructor { |
---|
66 | # defined below |
---|
67 | } |
---|
68 | # Used internally only. |
---|
69 | private method BuildConsole {} |
---|
70 | private method DebugConsole {} |
---|
71 | private method HideConsole {} |
---|
72 | private method ReceiveHelper {} |
---|
73 | private method SendDebugCommand {} |
---|
74 | private method SendHelper {} |
---|
75 | private method SendHelper.old {} |
---|
76 | private method ServerDown {} |
---|
77 | private method Shuffle { servers } |
---|
78 | private method TraceComm { channel {data {}} } |
---|
79 | private method WaitDialog { state } |
---|
80 | private method Waiting { option widget } |
---|
81 | |
---|
82 | protected method CheckConnection {} |
---|
83 | protected method Color2RGB { color } |
---|
84 | protected method ColorsToColormap { colors } |
---|
85 | protected method Connect { servers } |
---|
86 | protected method DisableWaitDialog {} |
---|
87 | protected method Disconnect {} |
---|
88 | protected method EnableWaitDialog { timeout } |
---|
89 | protected method Euler2XYZ { theta phi psi } |
---|
90 | protected method Flush {} |
---|
91 | protected method GetColormapList { args } |
---|
92 | protected method HandleError { args } |
---|
93 | protected method HandleOk { args } |
---|
94 | protected method IsConnected {} |
---|
95 | protected method ReceiveBytes { nbytes } |
---|
96 | protected method ReceiveEcho { channel {data ""} } |
---|
97 | protected method SendBytes { bytes } |
---|
98 | protected method SendCmd { string } |
---|
99 | protected method SendData { bytes } |
---|
100 | protected method SendEcho { channel {data ""} } |
---|
101 | protected method StartBufferingCommands {} |
---|
102 | protected method StartWaiting {} |
---|
103 | protected method StopBufferingCommands {} |
---|
104 | protected method StopWaiting {} |
---|
105 | protected method ToggleConsole {} |
---|
106 | |
---|
107 | private proc CheckNameList { namelist } { |
---|
108 | foreach host $namelist { |
---|
109 | set pattern {^[a-zA-Z0-9\.]+:[0-9]} |
---|
110 | if { ![regexp $pattern $host match] } { |
---|
111 | error "bad visualization server address \"$host\": should be host:port,host:port,..." |
---|
112 | } |
---|
113 | } |
---|
114 | } |
---|
115 | public proc GetServerList { type } { |
---|
116 | return $_servers($type) |
---|
117 | } |
---|
118 | public proc SetServerList { type namelist } { |
---|
119 | # Convert the comma separated list into a Tcl list. OGRE also adds |
---|
120 | # a trailing comma that we want to ignore. |
---|
121 | regsub -all "," $namelist " " namelist |
---|
122 | CheckNameList $namelist |
---|
123 | set _servers($type) $namelist |
---|
124 | } |
---|
125 | public proc RemoveServerFromList { type server } { |
---|
126 | if { ![info exists _servers($type)] } { |
---|
127 | error "unknown server type \"$type\"" |
---|
128 | } |
---|
129 | set i [lsearch $_servers($type) $server] |
---|
130 | if { $i < 0 } { |
---|
131 | return |
---|
132 | } |
---|
133 | set _servers($type) [lreplace $_servers($type) $i $i] |
---|
134 | } |
---|
135 | public proc SetPymolServerList { namelist } { |
---|
136 | SetServerList "pymol" $namelist |
---|
137 | } |
---|
138 | public proc SetNanovisServerList { namelist } { |
---|
139 | SetServerList "nanovis" $namelist |
---|
140 | } |
---|
141 | public proc SetVtkServerList { namelist } { |
---|
142 | SetServerList "vtk" $namelist |
---|
143 | } |
---|
144 | } |
---|
145 | |
---|
146 | itk::usual Panedwindow { |
---|
147 | keep -background -cursor |
---|
148 | } |
---|
149 | |
---|
150 | # ---------------------------------------------------------------------- |
---|
151 | # CONSTRUCTOR |
---|
152 | # ---------------------------------------------------------------------- |
---|
153 | itcl::body Rappture::VisViewer::constructor { servers args } { |
---|
154 | |
---|
155 | Rappture::dispatcher _dispatcher |
---|
156 | $_dispatcher register !serverDown |
---|
157 | $_dispatcher dispatch $this !serverDown "[itcl::code $this ServerDown]; list" |
---|
158 | $_dispatcher register !timeout |
---|
159 | $_dispatcher dispatch $this !timeout "[itcl::code $this Disconnect]; list" |
---|
160 | |
---|
161 | $_dispatcher register !waiting |
---|
162 | |
---|
163 | CheckNameList $servers |
---|
164 | set _buffer(in) "" |
---|
165 | set _buffer(out) "" |
---|
166 | # |
---|
167 | # Create a parser to handle incoming requests |
---|
168 | # |
---|
169 | set _parser [interp create -safe] |
---|
170 | foreach cmd [$_parser eval {info commands}] { |
---|
171 | $_parser hide $cmd |
---|
172 | } |
---|
173 | # Add default handlers for "ok" acknowledgement and server errors. |
---|
174 | $_parser alias ok [itcl::code $this HandleOk] |
---|
175 | $_parser alias viserror [itcl::code $this HandleError] |
---|
176 | |
---|
177 | # |
---|
178 | # Set up the widgets in the main body |
---|
179 | # |
---|
180 | option add hull.width hull.height |
---|
181 | pack propagate $itk_component(hull) no |
---|
182 | |
---|
183 | itk_component add main { |
---|
184 | Rappture::SidebarFrame $itk_interior.main -resizeframe 1 |
---|
185 | } |
---|
186 | pack $itk_component(main) -expand yes -fill both |
---|
187 | set f [$itk_component(main) component frame] |
---|
188 | |
---|
189 | itk_component add plotarea { |
---|
190 | frame $f.plotarea -highlightthickness 0 -background black |
---|
191 | } { |
---|
192 | ignore -background |
---|
193 | } |
---|
194 | pack $itk_component(plotarea) -fill both -expand yes |
---|
195 | set _image(plot) [image create photo] |
---|
196 | |
---|
197 | global env |
---|
198 | if { [info exists env(VISRECORDER)] } { |
---|
199 | set _logging 1 |
---|
200 | if { [file exists /tmp/recording.log] } { |
---|
201 | file delete /tmp/recording.log |
---|
202 | } |
---|
203 | } |
---|
204 | if { [info exists env(VISTRACE)] } { |
---|
205 | set _trace 1 |
---|
206 | } |
---|
207 | eval itk_initialize $args |
---|
208 | } |
---|
209 | |
---|
210 | # |
---|
211 | # destructor -- |
---|
212 | # |
---|
213 | itcl::body Rappture::VisViewer::destructor {} { |
---|
214 | $_dispatcher cancel !timeout |
---|
215 | interp delete $_parser |
---|
216 | array unset _done $this |
---|
217 | } |
---|
218 | |
---|
219 | # |
---|
220 | # Shuffle -- |
---|
221 | # |
---|
222 | # Shuffle the list of server hosts. |
---|
223 | # |
---|
224 | itcl::body Rappture::VisViewer::Shuffle { hosts } { |
---|
225 | set randomHosts {} |
---|
226 | set ticks [clock clicks] |
---|
227 | expr {srand($ticks)} |
---|
228 | for { set i [llength $hosts] } { $i > 0 } { incr i -1 } { |
---|
229 | set index [expr {round(rand()*$i - 0.5)}] |
---|
230 | if { $index == $i } { |
---|
231 | set index [expr $i - 1] |
---|
232 | } |
---|
233 | lappend randomHosts [lindex $hosts $index] |
---|
234 | set hosts [lreplace $hosts $index $index] |
---|
235 | } |
---|
236 | return $randomHosts |
---|
237 | } |
---|
238 | |
---|
239 | # |
---|
240 | # ServerDown -- |
---|
241 | # |
---|
242 | # Used internally to let the user know when the connection to the |
---|
243 | # visualization server has been lost. Puts up a tip encouraging the |
---|
244 | # user to press any control to reconnect. |
---|
245 | # |
---|
246 | itcl::body Rappture::VisViewer::ServerDown {} { |
---|
247 | if { [info exists itk_component(plotarea)] } { |
---|
248 | set x [expr {[winfo rootx $itk_component(plotarea)]+10}] |
---|
249 | set y [expr {[winfo rooty $itk_component(plotarea)]+10}] |
---|
250 | } else { |
---|
251 | set x 0; set y 0 |
---|
252 | } |
---|
253 | Rappture::Tooltip::cue @$x,$y "Lost connection to visualization server. This happens sometimes when there are too many users and the system runs out of memory.\n\nTo reconnect, reset the view or press any other control. Your picture should come right back up." |
---|
254 | } |
---|
255 | |
---|
256 | # |
---|
257 | # Connect -- |
---|
258 | # |
---|
259 | # Connect to the visualization server (e.g. nanovis, pymolproxy). |
---|
260 | # Creates an event callback that is triggered when we are idle |
---|
261 | # (no I/O with the server) for some specified time. |
---|
262 | # |
---|
263 | itcl::body Rappture::VisViewer::Connect { servers } { |
---|
264 | blt::busy hold $itk_component(hull) -cursor watch |
---|
265 | |
---|
266 | if { $_numConnectTries > $_maxConnects } { |
---|
267 | blt::busy release $itk_component(hull) |
---|
268 | set x [expr {[winfo rootx $itk_component(hull)]+10}] |
---|
269 | set y [expr {[winfo rooty $itk_component(hull)]+10}] |
---|
270 | Rappture::Tooltip::cue @$x,$y "Exceeded maximum number of connection attmepts to any $_serverType visualization server. Please contact support." |
---|
271 | return 0; |
---|
272 | } |
---|
273 | foreach server [Shuffle $servers] { |
---|
274 | puts stderr "connecting to $server..." |
---|
275 | foreach {hostname port} [split $server ":"] break |
---|
276 | if { [catch {socket $hostname $port} _sid] != 0 } { |
---|
277 | set _sid "" |
---|
278 | RemoveServerFromList $_serverType $server |
---|
279 | continue |
---|
280 | } |
---|
281 | incr _numConnectTries |
---|
282 | set _hostname $server |
---|
283 | fconfigure $_sid -translation binary -encoding binary |
---|
284 | |
---|
285 | # Read back the server identification string. |
---|
286 | if { [gets $_sid data] <= 0 } { |
---|
287 | set _sid "" |
---|
288 | puts stderr "ERORR reading from server data=($data)" |
---|
289 | RemoveServerFromList $_serverType $server |
---|
290 | continue |
---|
291 | } |
---|
292 | puts stderr "Render server is $data" |
---|
293 | # We're connected. Cancel any pending serverDown events and |
---|
294 | # release the busy window over the hull. |
---|
295 | $_dispatcher cancel !serverDown |
---|
296 | if { $_idleTimeout > 0 } { |
---|
297 | $_dispatcher event -after $_idleTimeout !timeout |
---|
298 | } |
---|
299 | blt::busy release $itk_component(hull) |
---|
300 | fconfigure $_sid -buffering line |
---|
301 | fileevent $_sid readable [itcl::code $this ReceiveHelper] |
---|
302 | return 1 |
---|
303 | } |
---|
304 | blt::busy release $itk_component(hull) |
---|
305 | set x [expr {[winfo rootx $itk_component(hull)]+10}] |
---|
306 | set y [expr {[winfo rooty $itk_component(hull)]+10}] |
---|
307 | Rappture::Tooltip::cue @$x,$y "Can't connect to any $_serverType visualization server. This may be a network problem. Wait a few moments and try resetting the view." |
---|
308 | return 0 |
---|
309 | } |
---|
310 | |
---|
311 | # |
---|
312 | # Disconnect -- |
---|
313 | # |
---|
314 | # Clients use this method to disconnect from the current rendering |
---|
315 | # server. Cancel any pending idle timeout events. |
---|
316 | # |
---|
317 | itcl::body Rappture::VisViewer::Disconnect {} { |
---|
318 | after cancel $_afterId |
---|
319 | $_dispatcher cancel !timeout |
---|
320 | catch {close $_sid} |
---|
321 | set _sid "" |
---|
322 | set _buffer(in) "" |
---|
323 | set _outbuf "" |
---|
324 | set _cmdSeq 0 |
---|
325 | } |
---|
326 | |
---|
327 | # |
---|
328 | # IsConnected -- |
---|
329 | # |
---|
330 | # Indicates if we are currently connected to a server. |
---|
331 | # |
---|
332 | itcl::body Rappture::VisViewer::IsConnected {} { |
---|
333 | if { $_sid == "" } { |
---|
334 | return 0 |
---|
335 | } |
---|
336 | if { [eof $_sid] } { |
---|
337 | set _sid "" |
---|
338 | return 0 |
---|
339 | } |
---|
340 | return 1 |
---|
341 | } |
---|
342 | |
---|
343 | # |
---|
344 | # CheckConection -- |
---|
345 | # |
---|
346 | # This routine is called whenever we're about to send/receive data on |
---|
347 | # the socket connection to the visualization server. If we're connected, |
---|
348 | # then reset the timeout event. Otherwise try to reconnect to the |
---|
349 | # visualization server. |
---|
350 | # |
---|
351 | itcl::body Rappture::VisViewer::CheckConnection {} { |
---|
352 | $_dispatcher cancel !timeout |
---|
353 | if { $_idleTimeout > 0 } { |
---|
354 | $_dispatcher event -after $_idleTimeout !timeout |
---|
355 | } |
---|
356 | if { [IsConnected] } { |
---|
357 | return 1 |
---|
358 | } |
---|
359 | if { $_sid != "" } { |
---|
360 | fileevent $_sid writable "" |
---|
361 | } |
---|
362 | # If we aren't connected, assume it's because the connection to the |
---|
363 | # visualization server broke. Try to open a connection and trigger a |
---|
364 | # rebuild. |
---|
365 | $_dispatcher cancel !serverDown |
---|
366 | set x [expr {[winfo rootx $itk_component(plotarea)]+10}] |
---|
367 | set y [expr {[winfo rooty $itk_component(plotarea)]+10}] |
---|
368 | Rappture::Tooltip::cue @$x,$y "Connecting..." |
---|
369 | set code [catch { Connect } ok] |
---|
370 | if { $code == 0 && $ok} { |
---|
371 | $_dispatcher event -idle !rebuild |
---|
372 | Rappture::Tooltip::cue hide |
---|
373 | } else { |
---|
374 | Rappture::Tooltip::cue @$x,$y "Can't connect to any $_serverType visualization server. This may be a network problem. Wait a few moments and try resetting the view." |
---|
375 | return 0 |
---|
376 | } |
---|
377 | return 1 |
---|
378 | } |
---|
379 | |
---|
380 | # |
---|
381 | # Flush -- |
---|
382 | # |
---|
383 | # Flushes the socket. |
---|
384 | # |
---|
385 | itcl::body Rappture::VisViewer::Flush {} { |
---|
386 | if { [CheckConnection] } { |
---|
387 | flush $_sid |
---|
388 | } |
---|
389 | } |
---|
390 | |
---|
391 | |
---|
392 | # |
---|
393 | # SendHelper -- |
---|
394 | # |
---|
395 | # Helper routine called from a file event to send data when the |
---|
396 | # connection is writable (i.e. not blocked). Sets a magic variable |
---|
397 | # _done($this) when we're done. |
---|
398 | # |
---|
399 | itcl::body Rappture::VisViewer::SendHelper {} { |
---|
400 | if { ![CheckConnection] } { |
---|
401 | return 0 |
---|
402 | } |
---|
403 | puts -nonewline $_sid $_buffer(out) |
---|
404 | flush $_sid |
---|
405 | set _buffer(out) "" |
---|
406 | set _done($this) 1; # Success |
---|
407 | } |
---|
408 | |
---|
409 | # |
---|
410 | # SendHelper.old -- |
---|
411 | # |
---|
412 | # Helper routine called from a file event to send data when the |
---|
413 | # connection is writable (i.e. not blocked). Sends data in chunks of 8k |
---|
414 | # (or less). Sets magic variable _done($this) to indicate that we're |
---|
415 | # either finished (success) or could not send bytes to the server |
---|
416 | # (failure). |
---|
417 | # |
---|
418 | itcl::body Rappture::VisViewer::SendHelper.old {} { |
---|
419 | if { ![CheckConnection] } { |
---|
420 | return 0 |
---|
421 | } |
---|
422 | set bytesLeft [string length $_buffer(out)] |
---|
423 | if { $bytesLeft > 0} { |
---|
424 | set chunk [string range $_buffer(out) 0 8095] |
---|
425 | set _buffer(out) [string range $_buffer(out) 8096 end] |
---|
426 | incr bytesLeft -8096 |
---|
427 | set code [catch { |
---|
428 | if { $bytesLeft > 0 } { |
---|
429 | puts -nonewline $_sid $chunk |
---|
430 | } else { |
---|
431 | puts $_sid $chunk |
---|
432 | } |
---|
433 | } err] |
---|
434 | if { $code != 0 } { |
---|
435 | puts stderr "error sending data to $_sid: $err" |
---|
436 | Disconnect |
---|
437 | set _done($this) 0; # Failure |
---|
438 | } |
---|
439 | } else { |
---|
440 | set _done($this) 1; # Success |
---|
441 | } |
---|
442 | } |
---|
443 | |
---|
444 | # |
---|
445 | # SendBytes -- |
---|
446 | # |
---|
447 | # Send a a string to the visualization server. |
---|
448 | # |
---|
449 | itcl::body Rappture::VisViewer::SendBytes { bytes } { |
---|
450 | SendEcho >>line $bytes |
---|
451 | if { ![CheckConnection] } { |
---|
452 | return 0 |
---|
453 | } |
---|
454 | StartWaiting |
---|
455 | # Even though the data is sent in only 1 "puts", we need to verify that |
---|
456 | # the server is ready first. Wait for the socket to become writable |
---|
457 | # before sending anything. |
---|
458 | set _done($this) 1 |
---|
459 | if {$_trace && $_buffer(out) != ""} { |
---|
460 | puts stderr "ERROR: re-entered SendBytes: buffer=([string range $_buffer(out) 0 70]...)" |
---|
461 | puts stderr "New cmd $_cmdSeq: [string range $bytes 0 70]..." |
---|
462 | } |
---|
463 | set _buffer(out) $bytes |
---|
464 | # There's problem when the user is interacting with the GUI at the |
---|
465 | # same time we're trying to write to the server. Don't want to |
---|
466 | # block because, the GUI will look like it's dead. We can start |
---|
467 | # by putting a busy window over plot so that inadvertent things like |
---|
468 | # mouse movements aren't received. |
---|
469 | if {$_blockOnWrite} { |
---|
470 | # Let's try this approach: allow a write to block so we don't |
---|
471 | # re-enter SendBytes |
---|
472 | SendHelper |
---|
473 | } else { |
---|
474 | # This can cause us to re-enter SendBytes during the tkwait, which |
---|
475 | # is not safe because the _buffer will be clobbered |
---|
476 | if { [info exists itk_component(main)] } { |
---|
477 | blt::busy hold $itk_component(main) -cursor "" |
---|
478 | } |
---|
479 | fileevent $_sid writable [itcl::code $this SendHelper] |
---|
480 | tkwait variable ::Rappture::VisViewer::_done($this) |
---|
481 | if { [info exists itk_component(main)] } { |
---|
482 | blt::busy release $itk_component(main) |
---|
483 | } |
---|
484 | } |
---|
485 | set _buffer(out) "" |
---|
486 | if { [IsConnected] } { |
---|
487 | # The connection may have closed while we were writing to the server. |
---|
488 | # This can happen if what we sent the server caused it to barf. |
---|
489 | fileevent $_sid writable "" |
---|
490 | flush $_sid |
---|
491 | } |
---|
492 | return $_done($this) |
---|
493 | } |
---|
494 | |
---|
495 | # |
---|
496 | # StartWaiting -- |
---|
497 | # |
---|
498 | # Display a waiting dialog after a timeout has passed |
---|
499 | # |
---|
500 | itcl::body Rappture::VisViewer::StartWaiting {} { |
---|
501 | if { $_waitTimeout > 0 } { |
---|
502 | after cancel $_afterId |
---|
503 | set _afterId [after $_waitTimeout [itcl::code $this WaitDialog on]] |
---|
504 | } |
---|
505 | } |
---|
506 | |
---|
507 | # |
---|
508 | # StopWaiting -- |
---|
509 | # |
---|
510 | # Take down waiting dialog |
---|
511 | # |
---|
512 | itcl::body Rappture::VisViewer::StopWaiting {} { |
---|
513 | if { $_waitTimeout > 0 } { |
---|
514 | WaitDialog off |
---|
515 | } |
---|
516 | } |
---|
517 | |
---|
518 | itcl::body Rappture::VisViewer::EnableWaitDialog { value } { |
---|
519 | set _waitTimeout $value |
---|
520 | } |
---|
521 | |
---|
522 | itcl::body Rappture::VisViewer::DisableWaitDialog {} { |
---|
523 | set _waitTimeout 0 |
---|
524 | } |
---|
525 | |
---|
526 | # |
---|
527 | # ReceiveBytes -- |
---|
528 | # |
---|
529 | # Read some number of bytes from the visualization server. |
---|
530 | # |
---|
531 | itcl::body Rappture::VisViewer::ReceiveBytes { size } { |
---|
532 | if { ![CheckConnection] } { |
---|
533 | return 0 |
---|
534 | } |
---|
535 | set bytes [read $_sid $size] |
---|
536 | ReceiveEcho <<line "<read $size bytes" |
---|
537 | StopWaiting |
---|
538 | return $bytes |
---|
539 | } |
---|
540 | |
---|
541 | # |
---|
542 | # ReceiveHelper -- |
---|
543 | # |
---|
544 | # Helper routine called from a file event when the connection is readable |
---|
545 | # (i.e. a command response has been sent by the rendering server. Reads |
---|
546 | # the incoming command and executes it in a safe interpreter to handle the |
---|
547 | # action. |
---|
548 | # |
---|
549 | # Note: This routine currently only handles command responses from |
---|
550 | # the visualization server. It doesn't handle non-blocking |
---|
551 | # reads from the visualization server. |
---|
552 | # |
---|
553 | # nv>image -bytes 100000 yes |
---|
554 | # ...following 100000 bytes... no |
---|
555 | # |
---|
556 | # Note: All commands from the render server are on one line. |
---|
557 | # This is because the render server can send anything |
---|
558 | # as an error message (restricted again to one line). |
---|
559 | # |
---|
560 | itcl::body Rappture::VisViewer::ReceiveHelper {} { |
---|
561 | if { ![CheckConnection] } { |
---|
562 | return 0 |
---|
563 | } |
---|
564 | set n [gets $_sid line] |
---|
565 | |
---|
566 | if { $n < 0 } { |
---|
567 | Disconnect |
---|
568 | return 0 |
---|
569 | } |
---|
570 | set line [string trim $line] |
---|
571 | if { $line == "" } { |
---|
572 | return |
---|
573 | } |
---|
574 | if { [string compare -length 3 $line "nv>"] == 0 } { |
---|
575 | ReceiveEcho <<line $line |
---|
576 | if ($_trace) { |
---|
577 | puts stderr "<<[string range $line 0 70]" |
---|
578 | } |
---|
579 | append _buffer(in) [string range $line 3 end] |
---|
580 | append _buffer(in) "\n" |
---|
581 | if {[info complete $_buffer(in)]} { |
---|
582 | set request $_buffer(in) |
---|
583 | set _buffer(in) "" |
---|
584 | if { [catch {$_parser eval $request} err] != 0 } { |
---|
585 | global errorInfo |
---|
586 | puts stderr "err=$err errorInfo=$errorInfo" |
---|
587 | } |
---|
588 | } |
---|
589 | } elseif { [string compare -length 21 $line "NanoVis Server Error:"] == 0 || |
---|
590 | [string compare -length 20 $line "VtkVis Server Error:"] == 0} { |
---|
591 | # this shows errors coming back from the engine |
---|
592 | ReceiveEcho <<error $line |
---|
593 | puts stderr "Render Server Error: $line\n" |
---|
594 | } else { |
---|
595 | # this shows errors coming back from the engine |
---|
596 | ReceiveEcho <<error $line |
---|
597 | puts stderr "Garbled message: $line\n" |
---|
598 | } |
---|
599 | } |
---|
600 | |
---|
601 | # |
---|
602 | # Color2RGB -- |
---|
603 | # |
---|
604 | # Converts a color name to a list of r,g,b values needed for the engine. |
---|
605 | # Each r/g/b component is scaled in the # range 0-1. |
---|
606 | # |
---|
607 | itcl::body Rappture::VisViewer::Color2RGB {color} { |
---|
608 | foreach {r g b} [winfo rgb $itk_component(hull) $color] break |
---|
609 | set r [expr {$r/65535.0}] |
---|
610 | set g [expr {$g/65535.0}] |
---|
611 | set b [expr {$b/65535.0}] |
---|
612 | return [list $r $g $b] |
---|
613 | } |
---|
614 | |
---|
615 | # |
---|
616 | # Euler2XYZ -- |
---|
617 | # |
---|
618 | # Converts euler angles for the camera placement the to angles of |
---|
619 | # rotation about the x/y/z axes, used by the engine. Returns a list: |
---|
620 | # {xangle, yangle, zangle}. |
---|
621 | # |
---|
622 | itcl::body Rappture::VisViewer::Euler2XYZ {theta phi psi} { |
---|
623 | set xangle [expr {$theta-90.0}] |
---|
624 | set yangle [expr {180.0-$phi}] |
---|
625 | set zangle $psi |
---|
626 | return [list $xangle $yangle $zangle] |
---|
627 | } |
---|
628 | |
---|
629 | # |
---|
630 | # SendEcho -- |
---|
631 | # |
---|
632 | # Used internally to echo sent data to clients interested in this widget. |
---|
633 | # If the -sendcommand option is set, then it is invoked in the global scope |
---|
634 | # with the <channel> and <data> values as arguments. Otherwise, this does |
---|
635 | # nothing. |
---|
636 | # |
---|
637 | itcl::body Rappture::VisViewer::SendEcho {channel {data ""}} { |
---|
638 | if { $_logging } { |
---|
639 | set f [open "/tmp/recording.log" "a"] |
---|
640 | fconfigure $f -translation binary -encoding binary |
---|
641 | puts -nonewline $f $data |
---|
642 | close $f |
---|
643 | } |
---|
644 | #puts stderr ">>($data)" |
---|
645 | if {[string length $itk_option(-sendcommand)] > 0} { |
---|
646 | uplevel #0 $itk_option(-sendcommand) [list $channel $data] |
---|
647 | } |
---|
648 | } |
---|
649 | |
---|
650 | # |
---|
651 | # ReceiveEcho -- |
---|
652 | # |
---|
653 | # Echoes received data to clients interested in this widget. If the |
---|
654 | # -receivecommand option is set, then it is invoked in the global scope |
---|
655 | # with the <channel> and <data> values as arguments. Otherwise, this |
---|
656 | # does nothing. |
---|
657 | # |
---|
658 | itcl::body Rappture::VisViewer::ReceiveEcho {channel {data ""}} { |
---|
659 | #puts stderr "<<line $data" |
---|
660 | if {[string length $itk_option(-receivecommand)] > 0} { |
---|
661 | uplevel #0 $itk_option(-receivecommand) [list $channel $data] |
---|
662 | } |
---|
663 | } |
---|
664 | |
---|
665 | itcl::body Rappture::VisViewer::WaitDialog { state } { |
---|
666 | after cancel $_afterId |
---|
667 | set _afterId -1 |
---|
668 | if { $state } { |
---|
669 | if { [winfo exists $itk_component(plotarea).view.splash] } { |
---|
670 | return |
---|
671 | } |
---|
672 | set inner [frame $itk_component(plotarea).view.splash] |
---|
673 | $inner configure -relief raised -bd 2 |
---|
674 | label $inner.text1 -text "Working...\nPlease wait." \ |
---|
675 | -font "Arial 10" |
---|
676 | label $inner.icon |
---|
677 | pack $inner -expand yes -anchor c |
---|
678 | blt::table $inner \ |
---|
679 | 0,0 $inner.text1 -anchor w \ |
---|
680 | 0,1 $inner.icon |
---|
681 | Waiting start $inner.icon |
---|
682 | } else { |
---|
683 | if { ![winfo exists $itk_component(plotarea).view.splash] } { |
---|
684 | return |
---|
685 | } |
---|
686 | Waiting stop $itk_component(plotarea).view.splash |
---|
687 | destroy $itk_component(plotarea).view.splash |
---|
688 | } |
---|
689 | } |
---|
690 | |
---|
691 | itcl::body Rappture::VisViewer::Waiting { option widget } { |
---|
692 | switch -- $option { |
---|
693 | "start" { |
---|
694 | $_dispatcher dispatch $this !waiting \ |
---|
695 | "[itcl::code $this Waiting "next" $widget] ; list" |
---|
696 | set _icon 0 |
---|
697 | $widget configure -image [Rappture::icon bigroller${_icon}] |
---|
698 | $_dispatcher event -after 150 !waiting |
---|
699 | } |
---|
700 | "next" { |
---|
701 | incr _icon |
---|
702 | if { $_icon >= 8 } { |
---|
703 | set _icon 0 |
---|
704 | } |
---|
705 | $widget configure -image [Rappture::icon bigroller${_icon}] |
---|
706 | $_dispatcher event -after 150 !waiting |
---|
707 | } |
---|
708 | "stop" { |
---|
709 | $_dispatcher cancel !waiting |
---|
710 | } |
---|
711 | } |
---|
712 | } |
---|
713 | |
---|
714 | # |
---|
715 | # HideConsole -- |
---|
716 | # |
---|
717 | # Hide the debug console by withdrawing its toplevel window. |
---|
718 | # |
---|
719 | itcl::body Rappture::VisViewer::HideConsole {} { |
---|
720 | set _debugConsole 0 |
---|
721 | DebugConsole |
---|
722 | } |
---|
723 | |
---|
724 | # |
---|
725 | # BuildConsole -- |
---|
726 | # |
---|
727 | # Create and pack the widgets that make up the debug console: a text |
---|
728 | # widget to display the communication and an entry widget to type |
---|
729 | # in commands to send to the render server. |
---|
730 | # |
---|
731 | itcl::body Rappture::VisViewer::BuildConsole {} { |
---|
732 | toplevel .renderconsole |
---|
733 | wm protocol .renderconsole WM_DELETE_WINDOW [itcl::code $this HideConsole] |
---|
734 | set f .renderconsole |
---|
735 | frame $f.send |
---|
736 | pack $f.send -side bottom -fill x |
---|
737 | label $f.send.l -text "Send:" |
---|
738 | pack $f.send.l -side left |
---|
739 | itk_component add command { |
---|
740 | entry $f.send.e -background white |
---|
741 | } { |
---|
742 | ignore -background |
---|
743 | } |
---|
744 | pack $f.send.e -side left -expand yes -fill x |
---|
745 | bind $f.send.e <Return> [itcl::code $this SendDebugCommand] |
---|
746 | bind $f.send.e <KP_Enter> [itcl::code $this SendDebugCommand] |
---|
747 | scrollbar $f.sb -orient vertical -command "$f.comm yview" |
---|
748 | pack $f.sb -side right -fill y |
---|
749 | itk_component add trace { |
---|
750 | text $f.comm -wrap char -yscrollcommand "$f.sb set" -background white |
---|
751 | } { |
---|
752 | ignore -background |
---|
753 | } |
---|
754 | pack $f.comm -expand yes -fill both |
---|
755 | bind $f.comm <Control-F1> [itcl::code $this ToggleConsole] |
---|
756 | bind $f.comm <Enter> [list focus %W] |
---|
757 | bind $f.send.e <Control-F1> [itcl::code $this ToggleConsole] |
---|
758 | |
---|
759 | $itk_component(trace) tag configure error -foreground red \ |
---|
760 | -font -*-courier-medium-o-normal-*-*-120-* |
---|
761 | $itk_component(trace) tag configure incoming -foreground blue |
---|
762 | } |
---|
763 | |
---|
764 | # |
---|
765 | # ToggleConsole -- |
---|
766 | # |
---|
767 | # This is used by derived classes to turn on/off debuging. It's |
---|
768 | # up the to derived class to decide how to turn on/off debugging. |
---|
769 | # |
---|
770 | itcl::body Rappture::VisViewer::ToggleConsole {} { |
---|
771 | if { $_debugConsole } { |
---|
772 | set _debugConsole 0 |
---|
773 | } else { |
---|
774 | set _debugConsole 1 |
---|
775 | } |
---|
776 | DebugConsole |
---|
777 | } |
---|
778 | |
---|
779 | # |
---|
780 | # DebugConsole -- |
---|
781 | # |
---|
782 | # Based on the value of the variable _debugConsole, turns on/off |
---|
783 | # debugging. This is done by setting/unsetting a procedure that |
---|
784 | # is called whenever new characters are received or sent on the |
---|
785 | # socket to the render server. Additionally, the debug console |
---|
786 | # is created if necessary and hidden/shown. |
---|
787 | # |
---|
788 | itcl::body Rappture::VisViewer::DebugConsole {} { |
---|
789 | if { ![winfo exists .renderconsole] } { |
---|
790 | BuildConsole |
---|
791 | } |
---|
792 | if { $_debugConsole } { |
---|
793 | $this configure -sendcommand [itcl::code $this TraceComm] |
---|
794 | $this configure -receivecommand [itcl::code $this TraceComm] |
---|
795 | wm deiconify .renderconsole |
---|
796 | } else { |
---|
797 | $this configure -sendcommand "" |
---|
798 | $this configure -receivecommand "" |
---|
799 | wm withdraw .renderconsole |
---|
800 | } |
---|
801 | } |
---|
802 | |
---|
803 | # ---------------------------------------------------------------------- |
---|
804 | # USAGE: TraceComm <channel> <data> |
---|
805 | # |
---|
806 | # Invoked automatically whenever there is communication between |
---|
807 | # the rendering widget and the server. Eavesdrops on the communication |
---|
808 | # and posts the commands in a text viewer. |
---|
809 | # ---------------------------------------------------------------------- |
---|
810 | itcl::body Rappture::VisViewer::TraceComm {channel {data ""}} { |
---|
811 | $itk_component(trace) configure -state normal |
---|
812 | switch -- $channel { |
---|
813 | closed { |
---|
814 | $itk_component(trace) insert end "--CLOSED--\n" error |
---|
815 | } |
---|
816 | <<line { |
---|
817 | $itk_component(trace) insert end $data incoming "\n" incoming |
---|
818 | } |
---|
819 | >>line { |
---|
820 | $itk_component(trace) insert end $data outgoing "\n" outgoing |
---|
821 | } |
---|
822 | error { |
---|
823 | $itk_component(trace) insert end $data error "\n" error |
---|
824 | } |
---|
825 | default { |
---|
826 | $itk_component(trace) insert end "$data\n" |
---|
827 | } |
---|
828 | } |
---|
829 | $itk_component(trace) configure -state disabled |
---|
830 | $itk_component(trace) see end |
---|
831 | } |
---|
832 | |
---|
833 | # ---------------------------------------------------------------------- |
---|
834 | # USAGE: SendDebugCommand |
---|
835 | # |
---|
836 | # Invoked automatically whenever the user enters a command and |
---|
837 | # presses <Return>. Sends the command along to the rendering |
---|
838 | # widget. |
---|
839 | # ---------------------------------------------------------------------- |
---|
840 | itcl::body Rappture::VisViewer::SendDebugCommand {} { |
---|
841 | incr _cmdSeq |
---|
842 | set cmd [$itk_component(command) get] |
---|
843 | append cmd "\n" |
---|
844 | if {$_trace} { |
---|
845 | puts stderr "$_cmdSeq>>[string range $cmd 0 70]" |
---|
846 | } |
---|
847 | SendBytes $cmd |
---|
848 | $itk_component(command) delete 0 end |
---|
849 | } |
---|
850 | |
---|
851 | # |
---|
852 | # HandleOk -- |
---|
853 | # |
---|
854 | # This handles the "ok" response from the server that acknowledges |
---|
855 | # the reception of a server command, but does not produce an image. |
---|
856 | # It may pass an argument such as "-token 9" that could be used to |
---|
857 | # determine how many commands have been processed by the server. |
---|
858 | # |
---|
859 | itcl::body Rappture::VisViewer::HandleOk { args } { |
---|
860 | if { $_waitTimeout > 0 } { |
---|
861 | StopWaiting |
---|
862 | } |
---|
863 | } |
---|
864 | |
---|
865 | # |
---|
866 | # HandleError -- |
---|
867 | # |
---|
868 | # This handles the "viserror" response from the server that reports |
---|
869 | # that a client-initiated error has occurred on the server. |
---|
870 | # |
---|
871 | itcl::body Rappture::VisViewer::HandleError { args } { |
---|
872 | array set info { |
---|
873 | -token "???" |
---|
874 | -bytes 0 |
---|
875 | -type "???" |
---|
876 | } |
---|
877 | array set info $args |
---|
878 | set bytes [ReceiveBytes $info(-bytes)] |
---|
879 | if { $info(-type) == "error" } { |
---|
880 | set popup $itk_component(hull).error |
---|
881 | if { ![winfo exists $popup] } { |
---|
882 | Rappture::Balloon $popup \ |
---|
883 | -title "Render Server Error" |
---|
884 | set inner [$popup component inner] |
---|
885 | label $inner.summary -text "" -anchor w |
---|
886 | |
---|
887 | Rappture::Scroller $inner.scrl \ |
---|
888 | -xscrollmode auto -yscrollmode auto |
---|
889 | text $inner.scrl.text \ |
---|
890 | -font "Arial 9 " -background white -relief sunken -bd 1 \ |
---|
891 | -height 5 -wrap word -width 60 |
---|
892 | $inner.scrl contents $inner.scrl.text |
---|
893 | button $inner.ok -text "Dismiss" -command [list $popup deactivate] \ |
---|
894 | -font "Arial 9" |
---|
895 | blt::table $inner \ |
---|
896 | 0,0 $inner.scrl -fill both \ |
---|
897 | 1,0 $inner.ok |
---|
898 | $inner.scrl.text tag configure normal -font "Arial 9" |
---|
899 | $inner.scrl.text tag configure italic -font "Arial 9 italic" |
---|
900 | $inner.scrl.text tag configure bold -font "Arial 10 bold" |
---|
901 | $inner.scrl.text tag configure code -font "Courier 10 bold" |
---|
902 | } else { |
---|
903 | $popup deactivate |
---|
904 | } |
---|
905 | update |
---|
906 | set inner [$popup component inner] |
---|
907 | $inner.scrl.text delete 0.0 end |
---|
908 | |
---|
909 | $inner.scrl.text configure -state normal |
---|
910 | $inner.scrl.text insert end "The following error was reported by the render server:\n\n" bold |
---|
911 | $inner.scrl.text insert end $bytes code |
---|
912 | $inner.scrl.text configure -state disabled |
---|
913 | update |
---|
914 | $popup activate $itk_component(hull) below |
---|
915 | } else { |
---|
916 | ReceiveEcho <<error $bytes |
---|
917 | puts stderr "Render server error:\n$bytes" |
---|
918 | } |
---|
919 | } |
---|
920 | |
---|
921 | itcl::body Rappture::VisViewer::GetColormapList { args } { |
---|
922 | array set opts { |
---|
923 | -includeDefault 0 |
---|
924 | -includeElementDefault 0 |
---|
925 | -includeNone 0 |
---|
926 | } |
---|
927 | if {[llength $args] > 0} { |
---|
928 | foreach opt $args { |
---|
929 | set opts($opt) 1 |
---|
930 | } |
---|
931 | } |
---|
932 | set colormaps [list] |
---|
933 | if {$opts(-includeDefault)} { |
---|
934 | lappend colormaps "default" "default" |
---|
935 | } |
---|
936 | if {$opts(-includeElementDefault)} { |
---|
937 | lappend colormaps "elementDefault" "elementDefault" |
---|
938 | } |
---|
939 | lappend colormaps \ |
---|
940 | "BCGYR" "BCGYR" \ |
---|
941 | "BGYOR" "BGYOR" \ |
---|
942 | "blue-to-brown" "blue-to-brown" \ |
---|
943 | "blue-to-orange" "blue-to-orange" \ |
---|
944 | "blue-to-grey" "blue-to-grey" \ |
---|
945 | "green-to-magenta" "green-to-magenta" \ |
---|
946 | "greyscale" "greyscale" \ |
---|
947 | "nanohub" "nanohub" \ |
---|
948 | "rainbow" "rainbow" \ |
---|
949 | "spectral" "spectral" \ |
---|
950 | "ROYGB" "ROYGB" \ |
---|
951 | "RYGCB" "RYGCB" \ |
---|
952 | "white-to-blue" "white-to-blue" \ |
---|
953 | "brown-to-blue" "brown-to-blue" \ |
---|
954 | "grey-to-blue" "grey-to-blue" \ |
---|
955 | "orange-to-blue" "orange-to-blue" |
---|
956 | if {$opts(-includeNone)} { |
---|
957 | lappend colormaps "none" "none" |
---|
958 | } |
---|
959 | return $colormaps |
---|
960 | } |
---|
961 | |
---|
962 | itcl::body Rappture::VisViewer::ColorsToColormap { colors } { |
---|
963 | set cmap {} |
---|
964 | switch -- $colors { |
---|
965 | "grey-to-blue" { |
---|
966 | set cmap { |
---|
967 | 0.0 0.200 0.200 0.200 |
---|
968 | 0.14285714285714285 0.400 0.400 0.400 |
---|
969 | 0.2857142857142857 0.600 0.600 0.600 |
---|
970 | 0.42857142857142855 0.900 0.900 0.900 |
---|
971 | 0.5714285714285714 0.800 1.000 1.000 |
---|
972 | 0.7142857142857143 0.600 1.000 1.000 |
---|
973 | 0.8571428571428571 0.400 0.900 1.000 |
---|
974 | 1.0 0.000 0.600 0.800 |
---|
975 | } |
---|
976 | } |
---|
977 | "blue-to-grey" { |
---|
978 | set cmap { |
---|
979 | 0.0 0.000 0.600 0.800 |
---|
980 | 0.14285714285714285 0.400 0.900 1.000 |
---|
981 | 0.2857142857142857 0.600 1.000 1.000 |
---|
982 | 0.42857142857142855 0.800 1.000 1.000 |
---|
983 | 0.5714285714285714 0.900 0.900 0.900 |
---|
984 | 0.7142857142857143 0.600 0.600 0.600 |
---|
985 | 0.8571428571428571 0.400 0.400 0.400 |
---|
986 | 1.0 0.200 0.200 0.200 |
---|
987 | } |
---|
988 | } |
---|
989 | "white-to-blue" { |
---|
990 | set cmap { |
---|
991 | 0.0 0.900 1.000 1.000 |
---|
992 | 0.1111111111111111 0.800 0.983 1.000 |
---|
993 | 0.2222222222222222 0.700 0.950 1.000 |
---|
994 | 0.3333333333333333 0.600 0.900 1.000 |
---|
995 | 0.4444444444444444 0.500 0.833 1.000 |
---|
996 | 0.5555555555555556 0.400 0.750 1.000 |
---|
997 | 0.6666666666666666 0.300 0.650 1.000 |
---|
998 | 0.7777777777777778 0.200 0.533 1.000 |
---|
999 | 0.8888888888888888 0.100 0.400 1.000 |
---|
1000 | 1.0 0.000 0.250 1.000 |
---|
1001 | } |
---|
1002 | } |
---|
1003 | "brown-to-blue" { |
---|
1004 | set cmap { |
---|
1005 | 0.0 0.200 0.100 0.000 |
---|
1006 | 0.09090909090909091 0.400 0.187 0.000 |
---|
1007 | 0.18181818181818182 0.600 0.379 0.210 |
---|
1008 | 0.2727272727272727 0.800 0.608 0.480 |
---|
1009 | 0.36363636363636365 0.850 0.688 0.595 |
---|
1010 | 0.45454545454545453 0.950 0.855 0.808 |
---|
1011 | 0.5454545454545454 0.800 0.993 1.000 |
---|
1012 | 0.6363636363636364 0.600 0.973 1.000 |
---|
1013 | 0.7272727272727273 0.400 0.940 1.000 |
---|
1014 | 0.8181818181818182 0.200 0.893 1.000 |
---|
1015 | 0.9090909090909091 0.000 0.667 0.800 |
---|
1016 | 1.0 0.000 0.480 0.600 |
---|
1017 | } |
---|
1018 | } |
---|
1019 | "blue-to-brown" { |
---|
1020 | set cmap { |
---|
1021 | 0.0 0.000 0.480 0.600 |
---|
1022 | 0.09090909090909091 0.000 0.667 0.800 |
---|
1023 | 0.18181818181818182 0.200 0.893 1.000 |
---|
1024 | 0.2727272727272727 0.400 0.940 1.000 |
---|
1025 | 0.36363636363636365 0.600 0.973 1.000 |
---|
1026 | 0.45454545454545453 0.800 0.993 1.000 |
---|
1027 | 0.5454545454545454 0.950 0.855 0.808 |
---|
1028 | 0.6363636363636364 0.850 0.688 0.595 |
---|
1029 | 0.7272727272727273 0.800 0.608 0.480 |
---|
1030 | 0.8181818181818182 0.600 0.379 0.210 |
---|
1031 | 0.9090909090909091 0.400 0.187 0.000 |
---|
1032 | 1.0 0.200 0.100 0.000 |
---|
1033 | } |
---|
1034 | } |
---|
1035 | "blue-to-orange" { |
---|
1036 | set cmap { |
---|
1037 | 0.0 0.000 0.167 1.000 |
---|
1038 | 0.09090909090909091 0.100 0.400 1.000 |
---|
1039 | 0.18181818181818182 0.200 0.600 1.000 |
---|
1040 | 0.2727272727272727 0.400 0.800 1.000 |
---|
1041 | 0.36363636363636365 0.600 0.933 1.000 |
---|
1042 | 0.45454545454545453 0.800 1.000 1.000 |
---|
1043 | 0.5454545454545454 1.000 1.000 0.800 |
---|
1044 | 0.6363636363636364 1.000 0.933 0.600 |
---|
1045 | 0.7272727272727273 1.000 0.800 0.400 |
---|
1046 | 0.8181818181818182 1.000 0.600 0.200 |
---|
1047 | 0.9090909090909091 1.000 0.400 0.100 |
---|
1048 | 1.0 1.000 0.167 0.000 |
---|
1049 | } |
---|
1050 | } |
---|
1051 | "orange-to-blue" { |
---|
1052 | set cmap { |
---|
1053 | 0.0 1.000 0.167 0.000 |
---|
1054 | 0.09090909090909091 1.000 0.400 0.100 |
---|
1055 | 0.18181818181818182 1.000 0.600 0.200 |
---|
1056 | 0.2727272727272727 1.000 0.800 0.400 |
---|
1057 | 0.36363636363636365 1.000 0.933 0.600 |
---|
1058 | 0.45454545454545453 1.000 1.000 0.800 |
---|
1059 | 0.5454545454545454 0.800 1.000 1.000 |
---|
1060 | 0.6363636363636364 0.600 0.933 1.000 |
---|
1061 | 0.7272727272727273 0.400 0.800 1.000 |
---|
1062 | 0.8181818181818182 0.200 0.600 1.000 |
---|
1063 | 0.9090909090909091 0.100 0.400 1.000 |
---|
1064 | 1.0 0.000 0.167 1.000 |
---|
1065 | } |
---|
1066 | } |
---|
1067 | "rainbow" { |
---|
1068 | set clist { |
---|
1069 | "#EE82EE" |
---|
1070 | "#4B0082" |
---|
1071 | "blue" |
---|
1072 | "#008000" |
---|
1073 | "yellow" |
---|
1074 | "#FFA500" |
---|
1075 | "red" |
---|
1076 | } |
---|
1077 | } |
---|
1078 | "BGYOR" { |
---|
1079 | set clist { |
---|
1080 | "blue" |
---|
1081 | "#008000" |
---|
1082 | "yellow" |
---|
1083 | "#FFA500" |
---|
1084 | "red" |
---|
1085 | } |
---|
1086 | } |
---|
1087 | "ROYGB" { |
---|
1088 | set clist { |
---|
1089 | "red" |
---|
1090 | "#FFA500" |
---|
1091 | "yellow" |
---|
1092 | "#008000" |
---|
1093 | "blue" |
---|
1094 | } |
---|
1095 | } |
---|
1096 | "RYGCB" { |
---|
1097 | set clist { |
---|
1098 | "red" |
---|
1099 | "yellow" |
---|
1100 | "green" |
---|
1101 | "cyan" |
---|
1102 | "blue" |
---|
1103 | } |
---|
1104 | } |
---|
1105 | "BCGYR" { |
---|
1106 | set clist { |
---|
1107 | "blue" |
---|
1108 | "cyan" |
---|
1109 | "green" |
---|
1110 | "yellow" |
---|
1111 | "red" |
---|
1112 | } |
---|
1113 | } |
---|
1114 | "spectral" { |
---|
1115 | set cmap { |
---|
1116 | 0.0 0.150 0.300 1.000 |
---|
1117 | 0.1 0.250 0.630 1.000 |
---|
1118 | 0.2 0.450 0.850 1.000 |
---|
1119 | 0.3 0.670 0.970 1.000 |
---|
1120 | 0.4 0.880 1.000 1.000 |
---|
1121 | 0.5 1.000 1.000 0.750 |
---|
1122 | 0.6 1.000 0.880 0.600 |
---|
1123 | 0.7 1.000 0.680 0.450 |
---|
1124 | 0.8 0.970 0.430 0.370 |
---|
1125 | 0.9 0.850 0.150 0.196 |
---|
1126 | 1.0 0.650 0.000 0.130 |
---|
1127 | } |
---|
1128 | } |
---|
1129 | "green-to-magenta" { |
---|
1130 | set cmap { |
---|
1131 | 0.0 0.000 0.316 0.000 |
---|
1132 | 0.06666666666666667 0.000 0.526 0.000 |
---|
1133 | 0.13333333333333333 0.000 0.737 0.000 |
---|
1134 | 0.2 0.000 0.947 0.000 |
---|
1135 | 0.26666666666666666 0.316 1.000 0.316 |
---|
1136 | 0.3333333333333333 0.526 1.000 0.526 |
---|
1137 | 0.4 0.737 1.000 0.737 |
---|
1138 | 0.4666666666666667 1.000 1.000 1.000 |
---|
1139 | 0.5333333333333333 1.000 0.947 1.000 |
---|
1140 | 0.6 1.000 0.737 1.000 |
---|
1141 | 0.6666666666666666 1.000 0.526 1.000 |
---|
1142 | 0.7333333333333333 1.000 0.316 1.000 |
---|
1143 | 0.8 0.947 0.000 0.947 |
---|
1144 | 0.8666666666666667 0.737 0.000 0.737 |
---|
1145 | 0.9333333333333333 0.526 0.000 0.526 |
---|
1146 | 1.0 0.316 0.000 0.316 |
---|
1147 | } |
---|
1148 | } |
---|
1149 | "greyscale" { |
---|
1150 | set cmap { |
---|
1151 | 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 |
---|
1152 | } |
---|
1153 | } |
---|
1154 | "nanohub" { |
---|
1155 | set clist "white yellow green cyan blue magenta" |
---|
1156 | } |
---|
1157 | default { |
---|
1158 | set clist [split $colors ":"] |
---|
1159 | } |
---|
1160 | } |
---|
1161 | if {$cmap == ""} { |
---|
1162 | if { [llength $clist] == 1 } { |
---|
1163 | set rgb [Color2RGB $clist] |
---|
1164 | append cmap "0.0 $rgb 1.0 $rgb" |
---|
1165 | } else { |
---|
1166 | for {set i 0} {$i < [llength $clist]} {incr i} { |
---|
1167 | set x [expr {double($i)/([llength $clist]-1)}] |
---|
1168 | set color [lindex $clist $i] |
---|
1169 | append cmap "$x [Color2RGB $color] " |
---|
1170 | } |
---|
1171 | } |
---|
1172 | } else { |
---|
1173 | regsub -all "\[ \t\r\n\]+" [string trim $cmap] " " cmap |
---|
1174 | } |
---|
1175 | return $cmap |
---|
1176 | } |
---|
1177 | |
---|
1178 | |
---|
1179 | # |
---|
1180 | # StartBufferingCommands -- |
---|
1181 | # |
---|
1182 | itcl::body Rappture::VisViewer::StartBufferingCommands { } { |
---|
1183 | incr _buffering |
---|
1184 | if { $_buffering == 1 } { |
---|
1185 | set _outbuf "" |
---|
1186 | } |
---|
1187 | } |
---|
1188 | |
---|
1189 | # |
---|
1190 | # StopBufferingCommands -- |
---|
1191 | # |
---|
1192 | # This gets called when we want to stop buffering the commands for |
---|
1193 | # the server and actually send then to the server. Note that there's |
---|
1194 | # a reference count on buffering. This is so that you can can |
---|
1195 | # Start/Stop multiple times without worrying about the current state. |
---|
1196 | # |
---|
1197 | itcl::body Rappture::VisViewer::StopBufferingCommands { } { |
---|
1198 | incr _buffering -1 |
---|
1199 | if { $_buffering == 0 } { |
---|
1200 | SendBytes $_outbuf |
---|
1201 | set _outbuf "" |
---|
1202 | } |
---|
1203 | } |
---|
1204 | |
---|
1205 | # |
---|
1206 | # SendCmd |
---|
1207 | # |
---|
1208 | # Send command off to the rendering server. If we're currently |
---|
1209 | # buffering, the command is queued to be sent later. |
---|
1210 | # |
---|
1211 | itcl::body Rappture::VisViewer::SendCmd {string} { |
---|
1212 | incr _cmdSeq |
---|
1213 | if {$_trace} { |
---|
1214 | puts stderr "$_cmdSeq>>[string range $string 0 70]" |
---|
1215 | } |
---|
1216 | if { $_buffering } { |
---|
1217 | append _outbuf $string "\n" |
---|
1218 | } else { |
---|
1219 | SendBytes "$string\n" |
---|
1220 | } |
---|
1221 | } |
---|
1222 | |
---|
1223 | # |
---|
1224 | # SendData |
---|
1225 | # |
---|
1226 | # Send data off to the rendering server. If we're currently |
---|
1227 | # buffering, the data is queued to be sent later. |
---|
1228 | # |
---|
1229 | itcl::body Rappture::VisViewer::SendData {bytes} { |
---|
1230 | if {$_trace} { |
---|
1231 | puts stderr "$_cmdSeq>>data payload" |
---|
1232 | } |
---|
1233 | if { $_buffering } { |
---|
1234 | append _outbuf $bytes |
---|
1235 | } else { |
---|
1236 | SendBytes $bytes |
---|
1237 | } |
---|
1238 | } |
---|