1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
<html lang="en">
<head>
<title>Example4 - Geomview Manual</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="Geomview Manual">
<meta name="generator" content="makeinfo 4.8">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Modules.html#Modules" title="Modules">
<link rel="prev" href="Example3.html#Example3" title="Example3">
<link rel="next" href="Module-Installation.html#Module-Installation" title="Module Installation">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
pre.display { font-family:inherit }
pre.format { font-family:inherit }
pre.smalldisplay { font-family:inherit; font-size:smaller }
pre.smallformat { font-family:inherit; font-size:smaller }
pre.smallexample { font-size:smaller }
pre.smalllisp { font-size:smaller }
span.sc { font-variant:small-caps }
span.roman { font-family:serif; font-weight:normal; }
span.sansserif { font-family:sans-serif; font-weight:normal; }
--></style>
</head>
<body>
<div class="node">
<p>
<a name="Example4"></a>
Next: <a rel="next" accesskey="n" href="Module-Installation.html#Module-Installation">Module Installation</a>,
Previous: <a rel="previous" accesskey="p" href="Example3.html#Example3">Example3</a>,
Up: <a rel="up" accesskey="u" href="Modules.html#Modules">Modules</a>
<hr>
</div>
<h3 class="section">6.6 Example 4: Simple Tcl/Tk Module Demonstrating Picking</h3>
<p>It's not necessary to write a Geomview module in C. The only requirement
of an external module is that it send GCL commands to its standard output
and expect responses (if any) on its standard input. An external module
can be written in C, perl, tcl/tk, or pretty much anything.
<p>As an example, assuming you have Tcl/Tk version 4.0 or later,
here's an external module with a simple GUI which demonstrates interaction with
geomview. This manual doesn't discuss the Tcl/Tk language; see the good book
on the subject by its originator John Ousterhout, published by Addison-Wesley,
titled <em>Tcl and the Tk Toolkit</em>.
<p>The `<samp><span class="samp">#!</span></samp>' on the script's first line causes the system to interpret
the script using the Tcl/Tk `<samp><span class="samp">wish</span></samp>' program; you might have to change its
first line if that's in some location other than /usr/local/bin/wish4.0.
Or, you could define it as a module using
<pre class="example"> (emodule-define "Pick Demo" "wish pickdemo.tcl")
</pre>
<p>in which case `<samp><span class="samp">wish</span></samp>' could be anywhere on the UNIX search path.
<pre class="example"> #! /usr/local/bin/wish4.0
# We use "fileevent" below to have "readsomething" be called whenever
# data is available from standard input, i.e. when geomview has sent us
# something. It promises to include a trailing newline, so we can use
# "gets" to read the geomview response, then parse its nested parentheses
# into tcl-friendly {} braces.
proc readsomething {} {
if {[gets stdin line] < 0} {
puts stderr "EOF on input, exiting..."
exit
}
regsub -all {\(} $line "\{" line
regsub -all {\)} $line "\}" line
# Strip outermost set of braces
set stuff [lindex $line 0]
# Invoke handler for whichever command we got. Could add others here,
# if we asked geomview for other kinds of data as well.
switch [lindex $stuff 0] {
pick {handlepick $stuff}
rawevent {handlekey $stuff}
}
}
# Fields of a "pick" response, from geomview manual:
# (pick COORDSYS GEOMID G V E F P VI EI FI)
# The pick command is executed internally in response to pick
# events (right mouse double click).
#
# COORDSYS = coordinate system in which coordinates of the following
# arguments are specified. This can be:
# world: world coord sys
# self: coord sys of the picked geom (GEOMID)
# primitive: coord sys of the actual primitive within
# the picked geom where the pick occurred.
# GEOMID = id of picked geom
# G = picked point (actual intersection of pick ray with object)
# V = picked vertex, if any
# E = picked edge, if any
# F = picked face
# P = path to picked primitive [0 or more]
# VI = index of picked vertex in primitive
# EI = list of indices of endpoints of picked edge, if any
# FI = index of picked face
# Report when user picked something.
#
proc handlepick {pick} {
global nameof selvert seledge order
set obj [lindex $pick 2]
set xyzw [lindex $pick 3]
set fv [lindex $pick 6]
set vi [lindex $pick 8]
set ei [lindex $pick 9]
set fi [lindex $pick 10]
# Report result, converting 4-component homogeneous point into 3-space point.
set w [lindex $xyzw 3]
set x [expr [lindex $xyzw 0]/$w]
set y [expr [lindex $xyzw 1]/$w]
set z [expr [lindex $xyzw 2]/$w]
set s "$x $y $z "
if {$vi >= 0} {
set s "$s vertex #$vi"
}
if {$ei != {}} {
set s "$s edge [lindex $ei 0]-[lindex $ei 1]"
}
if {$fi != -1} {
set s "$s face #$fi ([expr [llength $fv]/3]-gon)"
}
msg $s
}
# Having asked for notification of these raw events, we report when
# the user pressed these keys in the geomview graphics windows.
proc handlekey {event} {
global lastincr
switch [lindex $event 1] {
32 {msg "Pressed space bar"}
8 {msg "Pressed backspace key"}
}
}
#
# Display a message on the control panel, and on the terminal where geomview
# was started. We use ``puts stderr ...'' rather than simply ``puts ...'',
# since Geomview interprets anything we send to standard output
# as a GCL command!
#
proc msg {str} {
global msgtext
puts stderr $str
set msgtext $str
update
}
# Load object from file
proc loadobject {fname} {
if {$fname != ""} {
puts "(geometry thing < $fname)"
# Be sure to flush output to ensure geomview receives this now!
flush stdout
}
}
# Build simple "user interface"
# The message area could be a simple label rather than an entry box,
# but we want to be able to use X selection to copy text from it.
# The default mouse bindings do that automatically.
entry .msg -textvariable msgtext -width 45
pack .msg
frame .f
label .f.l -text "File to load:"
pack .f.l -side left
entry .f.ent -textvariable fname
pack .f.ent -side left -expand true -fill x
bind .f.ent <Return> { loadobject $fname }
pack .f
# End UI definition.
# Call "readsomething" when data arrives from geomview.
fileevent stdin readable {readsomething}
# Geomview initialization
puts {
(interest (pick primitive))
(interest (rawevent 32)) # Be notified when user presses space
(interest (rawevent 8)) # or backspace keys.
(geometry thing < hdodec.off)
(normalization world none)
}
# Flush to ensure geomview receives this.
flush stdout
wm title . {Sample external module}
msg "Click right mouse in graphics window"
</pre>
<!-- **************************************************************** -->
</body></html>
|