1 /*
2 * $Id: rezone.i,v 1.2 2010-04-18 10:33:38 thiebaut Exp $
3 * Point and click rezoner, written in interpreted Yorick.
4 */
5 /* Copyright (c) 2005, The Regents of the University of California.
6 * All rights reserved.
7 * This file is part of yorick (http://yorick.sourceforge.net).
8 * Read the accompanying LICENSE file for details.
9 */
10
11 require, "button.i";
12 require, "bowtie.i";
13
toy_mesh(filename)14 func toy_mesh(filename)
15 /* DOCUMENT toy_mesh, filename
16 generates a toy mesh in the file FILENAME in order to be able to
17 play with the rezone function. (FILENAME must be a string enclosed
18 in double quotes, of course.)
19 SEE ALSO: rezone
20 */
21 {
22 rt= span(1., 0., 6)(,-:1:11);
23 zt= span(0., 2., 11)(-:1:6,);
24 rt(3,3)+= 0.15;
25 zt(3,3)+= 0.15;
26 rt(3,7)+= 0.05;
27 zt(3,7)+= 0.25;
28 save, createb(filename), rt, zt;
29 }
30
31 extern rez_load_hook;
32 /* DOCUMENT rez_load_hook
33 If non-nil, filename to be included immediately after rez.i.
34 This file can be used to set personalized default values for the
35 many parameters.
36 Some parameters may be set before loading rez.i, as well
37 SEE ALSO: rez_kstyle, rez_lstyle
38 */
39
40 extern rez_kstyle;
41 extern rez_lstyle;
42 extern rez_color;
43 /* DOCUMENT rez_kstyle, rez_lstyle, rez_color
44 is a vector of three longs: [type,width,color]
45 type MUST be 1, 2, 3, 4, or 5,
46 width MUST be 1, 2, 3, 4, 5, 6, 7, or 8,
47 and color MUST be -1, -2, -3, -4, -5, -6, -7, -8, -9, or -10
48
49 Either or both parameters may be set before or after including
50 rez.i; by default:
51 rez_kstyle= [4, 1, -2] (dashdot, thin, foreground color)
52 rez_lstyle= [1, 1, -2] (solid, thin, foreground color)
53
54 To distinguish K and L by color instead of type, try:
55 rez_kstyle= [1, 1, -7] (dashdot, thin, blue)
56 rez_lstyle= [1, 1, -5] (solid, thin, red)
57 If the variable rez_color is true (non-nil and non-zero) when
58 this file is included, then these will be the default.
59
60 SEE ALSO: rez_load_hook
61 */
62 /* This choice distinguishes by line type. */
63 _old_rez_color= rez_color;
64 if (is_void(rez_kstyle)) rez_kstyle= rez_color? [1, 1, -7]:[4, 1, -2];
65 if (is_void(rez_lstyle)) rez_lstyle= rez_color? [1, 1, -5]:[1, 1, -2];
66
67 extern rez_mark;
68 /* DOCUMENT rez_mark
69 Causes rezone functions to mark bowtied or chevroned (boomeranged)
70 zones when the mesh is plotted. MUST have one of the following values:
71 0 to not mark bowtied or chevroned zones
72 1 to put a B at the center of the positive triangle of bowtied zones
73 2 to put a C at the center of the larger wing of chevroned zones
74 3 to mark both bowtied and chevroned zones
75
76 By default, rez_mark is 3; you may set it to a different value
77 either before or after including rez.i.
78
79 SEE ALSO: rez_mesh, rez_next, rez_prev, rez_drag
80 */
81 if (is_void(rez_mark)) rez_mark= 3;
82
83 _rez_on_black= 0;
84
85 extern rez_palette;
86 /* DOCUMENT rez_palette
87 3-by-ncolors array used as a palette when rez_regs region coloring
88 is set. The index in rez_regs is the second index into rez_palette.
89 The length 3 first index is [r,g,b].
90 The default is 15 pastels.
91 SEE ALSO: rez_regs
92 */
93 rez_palette= [[255,230,230],[230,255,230],[230,230,255],[242,242,230],
94 [230,242,242],[242,230,242],[236,249,230],[236,236,242],
95 [249,236,230],[230,236,249],[242,236,236],[230,249,236],
96 [249,230,236],[236,242,236],[236,230,249]];
97 _old_rez_palette= [];
98
99 func rez_chk_palette
100 {
101 if (typeof(rez_palette)!=typeof(_old_rez_palette) ||
102 dimsof(rez_palette)(1)!=dimsof(_old_rez_palette)(1) ||
103 anyof(dimsof(rez_palette)!=dimsof(_old_rez_palette)) ||
104 anyof(rez_palette!=_old_rez_palette)) {
105 if (dimsof(rez_palette)(2)!=3)
106 error, "rez_palette must be [[r1,g1,b1],[r2,g2,b2],...]";
107 if (!is_array(rez_palette) || typeof(rez_palette)=="struct_instance" ||
108 typeof(rez_palette)=="string" || typeof(rez_palette)=="complex" ||
109 min(rez_palette)<0 || max(rez_palette)>255)
110 error, "rez_palette values should be between 0 and 255";
111 palette, rez_palette(1,), rez_palette(2,), rez_palette(3,);
112 _old_rez_palette= rez_palette;
113 fma;
114 }
115 }
116
117 extern rez_regs;
118 /* DOCUMENT rez_regs
119 is a vector of region numbers which are to be drawn in the colors
120 specified in rez_palette. Thus:
121 rez_regs= [3,5]
122 causes regions 3 and 5 to be drawn in colors. All other regions have
123 white backgrounds. Hilighting too many regions in this way may slow
124 down the redraws unacceptably. To highlight all regions, use:
125 rez_regs= indgen(max(rez_ireg))
126 This won't work on monochrome monitors, of course.
127 The default is rez_regs=[].
128 SEE ALSO: rez_palette
129 */
130
131 extern rez_adjust_mesh;
132 /* DOCUMENT rez_adjust_mesh
133 is an optional hook function which is called after any change to the
134 mesh (e.g.- by dragging points) has been made. If it is defined, it
135 may modify the external variables rez_rt and rez_zt. This hook can
136 be used, for example, to force points along some k or l line to lie
137 along a symmetry line.
138 SEE ALSO: rezone, rez_all, rez_mesh
139 */
140
rez_plm(flag,adj_check)141 func rez_plm(flag, adj_check)
142 {
143 if (adj_check && is_func(rez_adjust_mesh)) rez_adjust_mesh;
144
145 fma;
146
147 extern rez_kstyle, rez_lstyle;
148 if (rez_color!=_old_rez_color) {
149 rez_kstyle= rez_color? [1, 1, -7]:[4, 1, -2];
150 rez_lstyle= rez_color? [1, 1, -5]:[1, 1, -2];
151 _old_rez_color= rez_color;
152 }
153
154 if (!is_void(rez_regs)) {
155 rez_chk_palette;
156 n= numberof(rez_regs);
157 colors= array(char, dimsof(rez_rt)(2), dimsof(rez_rt)(3));
158 for (i=1 ; i<=n ; i++) {
159 reg= rez_regs(i);
160 if (noneof(rez_ireg==reg) || reg<=0) continue;
161 colors(where(rez_ireg==reg))= i-1;
162 plf, colors, rez_rt, rez_zt, rez_ireg, legend=string(0), region=reg;
163 }
164 } else if (_rez_on_black) {
165 rez_ptexist;
166 list= where(rez_ptx);
167 r= rez_rt(list);
168 z= rez_zt(list);
169 pli, [['\0']], min(z), min(r), max(z), max(r);
170 }
171
172 plm, rez_rt, rez_zt, rez_ireg, legend=string(0), inhibit=1,
173 color= rez_kstyle(3), width= rez_kstyle(2), type= rez_kstyle(1);
174 plm, rez_rt, rez_zt, rez_ireg, legend=string(0), inhibit=2,
175 color= rez_lstyle(3), width= rez_lstyle(2), type= rez_lstyle(1);
176
177 if (rez_mark&3) {
178 extern rez_map;
179 local rr, zz;
180 if (flag || is_void(flag)) {
181 if (_rez_polar) {
182 zt= rez_zt*cos(rez_rt);
183 rt= rez_zt*sin(rez_rt);
184 } else {
185 zt= rez_zt;
186 rt= rez_rt;
187 }
188 rez_map= bowtie(rt,zt,rez_ireg);
189 }
190 for (i=1 ; i<=2 ; i++) {
191 if (!(rez_mark&i)) continue;
192 rez_getrz, where(rez_map==(i-1));
193 if (!is_void(rr)) {
194 a1= (rr(2,2,)-rr(2,1,))*(zz(2,1,)-zz(1,1,)) -
195 (zz(2,2,)-zz(2,1,))*(rr(2,1,)-rr(1,1,));
196 a2= (rr(1,1,)-rr(1,2,))*(zz(1,2,)-zz(2,2,)) -
197 (zz(1,1,)-zz(1,2,))*(rr(1,2,)-rr(2,2,));
198 a3= (rr(2,1,)-rr(1,1,))*(zz(1,1,)-zz(1,2,)) -
199 (zz(2,1,)-zz(1,1,))*(rr(1,1,)-rr(1,2,));
200 if (i==1) {
201 /* this is a magic trick for bowtied zones */
202 index= ((a3>=0.) | (a1>=0.)<<1 | (a2>=0.)<<2) - 1;
203 p1= [1,0,3,2](index);
204 p2= [3,1,2,0](index);
205 p3= [2,3,0,1](index);
206 p4= [0,2,1,3](index);
207 index= indgen(1:numberof(rr):4);
208 p1+= index;
209 p2+= index;
210 p3+= index;
211 p4+= index;
212 /* now p1 p2 p3 p4 are the indices of the points in (rr,zz)
213 with p1 p2 being the positive edge of the bowtied zone,
214 so that p1 p3 and p2 p4 cross */
215 r1= rr(p1);
216 z1= zz(p1);
217 r2= rr(p2);
218 z2= zz(p2);
219 r3= rr(p3);
220 z3= zz(p3);
221 r4= rr(p4);
222 z4= zz(p4);
223 fa= (r3-r2)*(z4-z1);
224 fb= -(r4-r1)*(z3-z2);
225 det= fa+fb;
226 fa/= det;
227 fb/= det;
228 rr= r1*fa + r2*fb + (r3-r2)*(r4-r1)*(z2-z1)/det;
229 zz= z2*fa + z1*fb - (z3-z2)*(z4-z1)*(r2-r1)/det;
230 rr= (rr+r1+r2)/3.0;
231 zz= (zz+z1+z2)/3.0;
232 marker= 'B';
233 legend= "B: bowtied zones";
234 } else {
235 a4= (rr(1,2,)-rr(2,2,))*(zz(2,2,)-zz(2,1,)) -
236 (zz(1,2,)-zz(2,2,))*(rr(2,2,)-rr(2,1,));
237 r1= (rr(1,1,)+rr(2,1,)+rr(2,2,))/3.0;
238 z1= (zz(1,1,)+zz(2,1,)+zz(2,2,))/3.0;
239 r2= (rr(1,1,)+rr(2,2,)+rr(1,2,))/3.0;
240 z2= (zz(1,1,)+zz(2,2,)+zz(1,2,))/3.0;
241 r3= (rr(2,1,)+rr(1,1,)+rr(1,2,))/3.0;
242 z3= (zz(2,1,)+zz(1,1,)+zz(1,2,))/3.0;
243 r4= (rr(1,2,)+rr(2,2,)+rr(2,1,))/3.0;
244 z4= (zz(1,2,)+zz(2,2,)+zz(2,1,))/3.0;
245 mask= (a1>0. & a2>0.);
246 which= [a1*mask,a2*mask,a3*(1-mask),a4*(1-mask)](,mxx);
247 n= numberof(a1);
248 list= indgen(n)+n*(which-1);
249 rr= [r1,r2,r3,r4](list);
250 zz= [z1,z2,z3,z4](list);
251 marker= 'C';
252 legend= "C: chevroned zones";
253 }
254 plg,rr,zz,type=0,marker=marker,legend=legend;
255 }
256 }
257 }
258 }
259
260 _rez_polar= 0n;
261
262 func rez_toggle
263 {
264 zt= rez_zt;
265 rt= rez_rt;
266 _rez_polar= !_rez_polar;
267 if (_rez_polar) {
268 rez_zt= abs(rt,zt);
269 rez_rt= atan(rt,zt+1.e-99);
270 } else {
271 rez_zt= zt*cos(rt);
272 rez_rt= zt*sin(rt);
273 }
274 }
275
276 /* These four parameters specify the viewport position, which is actually
277 a function of the stylesheet being used, and potentially changes as
278 a function of window or coordinate system within the window. The numbers
279 here should work decently for the work.gs and boxed.gs styles. If you
280 set them very large, the only side effect is that clicking way outside
281 the coordinate system (e.g.- missing the Done or Undo button) will pick
282 up the nearest mesh vertex). This is not that unreasonable a behavior,
283 especially since any miscue can be undone. See rez_load_hook. */
284 _rez_xvp= (0.615+0.175)*0.5;
285 _rez_dxvp= (0.615-0.175)*0.5;
286 _rez_yvp= (0.895+0.455)*0.5;
287 _rez_dyvp= (0.895-0.455)*0.5;
288 /* Following setup could be placed in rez_load_hook to allow any style:
289 _rez_xvp= 0.5;
290 _rez_dxvp= 0.6;
291 _rez_yvp= 0.5;
292 _rez_dyvp= 0.6;
293 */
294
295 func rezone(filename, all=, quiet=)
296 /* DOCUMENT rezone, filename
297 or rezone
298
299 Invoke the mouse-driven rezoner. Input is taken from variables
300 rt, zt, and ireg in the file FILENAME (which is prompted for if
301 omitted). Output is written to a different file as rt, zt, and
302 ireg. The output file also contains copies rez_rt, rez_zt, and
303 rez_ireg in case the mesh under a different name is desirable,
304 as well as rez_rt0, rez_zt0, and rez_ireg0, which are the original
305 mesh.
306
307 If you click on [Escape], you may continue rezoning where you left
308 off by typing rezone with no arguments.
309
310 When you are finished, click [OK] to write the output file.
311
312 Use [Zoom or Pan] and [Set Styles] to change the plot limits or
313 line colors and styles. The [Zoom or Pan] screen has buttons which
314 "warp" you to each bowtied or chevroned "problem" zone, as well as
315 a button to toggle between rectangular and polar coordinates.
316
317 Click [Drag Points] to drag points one at a time with the mouse.
318
319 Click [Adjust Line] to smooth the points on logical line segments.
320 You first click on the endpoints P and Q, then click a button to
321 smooth or equal space the poionts between P and Q, or drag any
322 point between P and Q to establish equal ratio zones ("ER" operation).
323
324 Click [Adjust Region] to smooth the points in logically rectangular
325 regions. You first click on the opposite corners P and R of the
326 rectangle PQRS, then click a button to smooth the interior points,
327 or click on a point on one of the four edges to transfer the spacing
328 on that edge throughout the region PQRS ("EQ" operation).
329
330 The [Undo] (or [Redo]) button removes the effect of the most
331 recent drag points, adjust line, or adjust region operation.
332
333 Hints:
334 (0) After [Escape], the current mesh is in the variables
335 rez_zt, rez_rt, and rez_ireg. You can change these
336 variables "by hand" before restarting rezone to make
337 algebraic adjustments.
338 (1) Switch to polar coordinates during an [Adjust Line] or
339 [Adjust Region] in order to get points to lie along a
340 circular arc. If your center point is not (0,0), you
341 will need to [Escape] and subtract your center point
342 from the rez_zt and rez_rt variables yourself, then
343 [Escape] a second time to restore the proper coordinates
344 before you write the output file.
345 (2) You can select a center point as the second point during
346 [Adjust Line] or [Adjust Region]. When you do this, the
347 K (or L) value of this second point will be the same as
348 that of the first point -- otherwise there is no way to
349 distinguish among all of the logical points at the center.
350 In an [Adjust Region], the center point will be labeled
351 Q instead of R as usual, and you will need to choose a
352 third point (S) to complete the rectangle PQRS.
353 (3) If you set the variable rez_color=1 before you include
354 rezone.i, you will get K lines and L lines drawn in different
355 colors instead of the default (which is K lines dashdot and
356 L lines solid).
357 (4) If you have a color monitor, you can set rez_regs before
358 invoking rezone in order to highlight a list of regions.
359
360 The ALL keyword will be passed to the nbow function, which will
361 not be called if the QUIET keyword is non-nil and non-zero. By
362 default, a short summary of bowtied and chevroned zones is printed.
363
364 If you need help on how to use one of the screens, try getting
365 help on the appropriate on of these see-also topics, e.g.-
366 help, rez_style
367 to get help on the [Set Styles] screen.
368
369 SEE ALSO: rez_all, rez_drag, rez_ladj, rez_radj, rez_zoom, rez_style,
370 rez_color, rez_regs, rez_adjust_mesh, toy_mesh
371 */
372 {
373 extern rez_name;
374 if (is_void(filename)) {
375 if (is_void(rez_name)) {
376 filename= "";
377 read, format="%s", prompt="Name of Z-file: ", filename;
378 }
379 }
380 if (!is_void(filename)) {
381 /* begin a new rezone */
382 for (i=1 ; i<=2 ; i++) {
383 if (!is_void(open(filename,"rb",1))) break;
384 write, "Cannot open "+filename;
385 read, format="%s", prompt="Name of Z-file: ", filename;
386 }
387 if (i>2) {
388 write, "Quitting rezone";
389 return;
390 }
391 rez_mesh, openb(filename), quiet=quiet, all=all;
392 if (!is_void(rez_zt) && !is_void(rez_rt)) rez_name= filename;
393 write, "For help, click [Escape], then type: help, rezone";
394 }
395
396 esca= rez_all();
397 if (_rez_polar) rez_toggle;
398 if (esca) return;
399
400 default= rez_name+"_rez";
401 for (i=1 ; i<=3 ; i++) {
402 line=
403 rdline(prompt="Output filename (default "+default+", ? to escape): ");
404 line= strtok(line)(1);
405 if (!line) line= default;
406 else if (line=="?") line= string(0);
407 if (line!=rez_name) break;
408 }
409 if (!line || line==rez_name) {
410 write, "Escaping from rezone -- to resume, type rezone";
411 return;
412 }
413
414 zt= rez_zt;
415 rt= rez_rt;
416 ireg= rez_ireg;
417 at_pdb_close|= 1;
418 save, createb(line), zt, rt, ireg, rez_zt, rez_rt, rez_ireg,
419 rez_zt0, rez_rt0, rez_ireg0;
420
421 rez_name= [];
422 }
423
rez_all(dummy)424 func rez_all(dummy)
425 /* DOCUMENT rez_all
426 Click on [Drag Points] to drag points around with the mouse with
427 rez_drag.
428
429 Click on [Adjust Line] to adjust points along a line segment with
430 rez_ladj.
431
432 Click on [Adjust Region] to adjust points in a rectangular region
433 with rez_radj.
434
435 Click on the [Undo] button to undo the previous change.
436 Click on the [Redo] button to redo the previous undo.
437 Click on the [Revert] to return to the original mesh.
438
439 When you are finished moving points around, click on [OK].
440 Click on [Escape] to exit with a non-zero return value.
441
442 Click on [Zoom or Pan] to change the plot limits (see rez_zoom).
443
444 Click on [Set Styles] to change the line styles or colors (see
445 rez_style).
446
447 SEE ALSO: rez_ladj, rez_mesh, rez_zoom, rez_style, rez_adjust_mesh
448 */
449 {
450 done= Button(text="OK",x=.203,y=.895,dx=.020,dy=.012);
451 undo= Button(text="Undo",x=.254,y=.895,dx=.025,dy=.012);
452 esca= Button(text="Escape",x=.344,y=.895,dx=.035,dy=.012);
453 zorp= Button(text="Zoom or Pan",x=.464,y=.895,dx=.054,dy=.012);
454 sets= Button(text="Set Styles",x=.569,y=.895,dx=.045,dy=.012);
455 drag= Button(text="Drag Points",x=.240,y=.375,dx=.054,dy=.012);
456 ladj= Button(text="Adjust Line",x=.350,y=.375,dx=.050,dy=.012);
457 radj= Button(text="Adjust Region",x=.468,y=.375,dx=.062,dy=.012);
458 reve= Button(text="Revert",x=.577,y=.375,dx=.030,dy=.012);
459
460 rez_plm, 1;
461 button_plot, done, undo, esca, zorp, sets, drag, ladj, radj, reve;
462
463 zt= zt2= rez_zt;
464 rt= rt2= rez_rt;
465
466 for (;;) {
467 m= mouse(1, 2, "");
468 if (is_void(m)) { rdline,prompt=""; continue; }
469 x= m(5);
470 y= m(6);
471 if (button_test(done,x,y)) break;
472 if (button_test(esca,x,y)) {
473 write, "Escaping from rezone -- to resume, type rezone";
474 rez_plm,1;
475 return 1;
476 }
477 if (button_test(undo,x,y)) {
478 if (undo.text=="Undo") {
479 rez_zt= zt;
480 rez_rt= rt;
481 undo.text= "Redo";
482 } else {
483 rez_zt= zt2;
484 rez_rt= rt2;
485 undo.text= "Undo";
486 }
487 rez_plm, 1;
488 } else if (button_test(reve,x,y)) {
489 zt= rez_zt;
490 rt= rez_rt;
491 undo.text= "Undo";
492 rez_zt= zt2= rez_zt0;
493 rez_rt= rt2= rez_rt0;
494 rez_plm, 1;
495 } else if (button_test(zorp,x,y)) {
496 rez_zoom;
497 rez_plm, 0;
498 } else if (button_test(sets,x,y)) {
499 rez_style;
500 rez_plm, 0;
501 } else if (button_test(drag,x,y)) {
502 zt= rez_zt;
503 rt= rez_rt;
504 undo.text= "Undo";
505 rez_drag;
506 zt2= rez_zt;
507 rt2= rez_rt;
508 } else if (button_test(ladj,x,y)) {
509 zt= rez_zt;
510 rt= rez_rt;
511 undo.text= "Undo";
512 rez_ladj;
513 zt2= rez_zt;
514 rt2= rez_rt;
515 } else if (button_test(radj,x,y)) {
516 zt= rez_zt;
517 rt= rez_rt;
518 undo.text= "Undo";
519 rez_radj;
520 zt2= rez_zt;
521 rt2= rez_rt;
522 } else {
523 rez_ding;
524 continue;
525 }
526 button_plot, done, undo, esca, zorp, sets, drag, ladj, radj, reve;
527 }
528
529 rez_plm, 1;
530 return 0;
531 }
532
533 func rez_drag
534 /* DOCUMENT rez_drag
535 Allow points in the rezone mesh to be dragged around with
536 the mouse. Press mouse button near a vertex, move mouse
537 to desired position of that vertex, and release button.
538 If the point where you click is less than twice the distance to the
539 second closest point than to the nearest point, the point will not
540 be moved (you will hear a beep when you release the button).
541 Click on the [Undo] button to undo the previous move; you can undo
542 up to 100 previous moves by successive [Undo] clicks.
543
544 When you are finished moving points around, click on [OK].
545
546 Click on [Zoom or Pan] to change the plot limits (see rez_zoom).
547
548 Click on [Set Styles] to change the line styles or colors (see
549 rez_style).
550
551 SEE ALSO: rez_ladj, rez_radj, rez_mesh, rez_zoom, rez_style
552 */
553 {
554 done= Button(text="OK",x=.203,y=.895,dx=.020,dy=.012);
555 undo= Button(text="Undo",x=.254,y=.895,dx=.025,dy=.012);
556 lab1= Button(text="Drag points.",x=.344,y=.895,dx=.050,dy=.012,width=-1);
557 zorp= Button(text="Zoom or Pan",x=.464,y=.895,dx=.054,dy=.012);
558 sets= Button(text="Set Styles",x=.569,y=.895,dx=.045,dy=.012);
559
560 rez_plm, 1;
561 button_plot, done, undo, lab1, zorp, sets;
562
563 list= array(0.0, 3, 100); /* keep last 100 moves for undo */
564
565 kmax= dimsof(rez_rt)(2);
566 for (;;) {
567 m= mouse(1, 2, "");
568 if (is_void(m)) { rdline,prompt=""; continue; }
569 flag= j= 0;
570 if (button_test(done,m(5),m(6))) break;
571 if (button_test(undo,m(5),m(6))) {
572 j= long(list(1,1));
573 zt= list(2,1);
574 rt= list(3,1);
575 list(,1:-1)= list(,2:0);
576 list(,0)= 0.0;
577 flag= 1;
578 } else if (button_test(zorp,m(5),m(6))) {
579 rez_zoom;
580 flag= j= 2;
581 } else if (button_test(sets,m(5),m(6))) {
582 rez_style;
583 flag= j= 2;
584 } else if (abs(_rez_xvp-m(5))<=_rez_dxvp ||
585 abs(_rez_yvp-m(6))<=_rez_dyvp) {
586 j= rez_find(m(1), m(2));
587 if (numberof(_rez_center)) j= 0;
588 zt= m(3);
589 rt= m(4);
590 }
591 if (j<1) {
592 rez_ding;
593 } else {
594 if (flag<2) {
595 if (!flag) {
596 list(,2:0)= list(,1:-1);
597 list(1,1)= j;
598 list(2,1)= rez_zt(j);
599 list(3,1)= rez_rt(j);
600 }
601 rez_zt(j)= zt;
602 rez_rt(j)= rt;
603 }
604 rez_plm, (flag<2), 1;
605 button_plot, done, undo, lab1, zorp, sets;
606 if (!flag) {
607 text= swrite(format="moved (%ld,%ld)",(j-1)%kmax+1,(j-1)/kmax+1);
608 plt, text, 0.35, 0.375;
609 }
610 }
611 }
612
613 rez_plm, 1;
614 }
615
616 func rez_ladj
617 /* DOCUMENT rez_ladj
618 Adjust the points along a logical line segment PQ:
619
620 Click on [Set P] or [Set Q] to set the endpoints of the segment.
621 When P and Q have been set, click [OK]; this button will
622 read [Cancel] if P and Q do not have either the same K or the
623 same L index.
624
625 Click on [Smooth] to smooth the points along PQ.
626
627 Click on [Equal Space] to make the points along PQ equally spaced.
628 This forces PQ to be a straight line.
629
630 Drag any point between P and Q to get equal ratio spacing of all
631 the points between P and Q. This also forces PQ to be a straight
632 line; if PQ is initially curved, you may want to click on
633 [Equal Space] before you attempt to drag points.
634
635 Click on the [Undo] button to undo the previous adjustment; you can
636 undo up to 20 previous adjustments by successive [Undo] clicks.
637
638 When you are finished adjusting lines, click on [OK].
639
640 Click on [Zoom or Pan] to change the plot limits (see rez_zoom).
641
642 Click on [Set Styles] to change the line styles or colors (see
643 rez_style).
644
645 Hint:
646 You can select a center point as the second point during
647 rez_ladj. When you do this, the K (or L) value of this second
648 point will be the same as that of the first point --
649 otherwise there is no way to distinguish among all of the
650 logical points at the center.
651
652 SEE ALSO: rez_drag, rez_radj, rez_mesh, rez_zoom, rez_style
653 */
654 {
655 done= Button(text="OK",x=.203,y=.895,dx=.020,dy=.012);
656 undo= Button(text="Undo",x=.254,y=.895,dx=.025,dy=.012);
657 lab1= Button(text="Adjust line.",x=.344,y=.895,dx=.050,dy=.012,width=-1);
658 zorp= Button(text="Zoom or Pan",x=.464,y=.895,dx=.054,dy=.012);
659 sets= Button(text="Set Styles",x=.569,y=.895,dx=.045,dy=.012);
660
661 setp= Button(text="Set P",x=.208,y=.375,dx=.027,dy=.012);
662 setq= Button(text="Set Q",x=.268,y=.375,dx=.027,dy=.012);
663 drag= Button(text="Drag for ER",x=.355,y=.375,
664 dx=.035,dy=.012,width=-1);
665 smth= Button(text="Smooth",x=.454,y=.375,dx=.035,dy=.012);
666 eqsp= Button(text="Equal Space",x=.550,y=.375,dx=.054,dy=.012);
667
668 mode= 1;
669 jP= jQ= oldjP= oldjQ= 0;
670 rez_plm, 1;
671 kmax= dimsof(rez_rt)(2);
672 lab1.text= "Select P.";
673 setp.text= "Set Q";
674 done.text= "Cancel";
675 done.dx= 0.033;
676 button_plot, done, lab1, zorp, sets, setp;
677
678 for (;;) {
679 m= mouse(1, 2, "");
680 if (is_void(m)) { rdline,prompt=""; continue; }
681 x= m(5);
682 y= m(6);
683 if (button_test(zorp,x,y)) {
684 rez_zoom;
685 } else if (button_test(sets,x,y)) {
686 rez_style;
687 } else if (button_test(setp,x,y)) {
688 mode= 1 + (setp.text!="Set P");
689 if (mode==1) {
690 lab1.text= "Select P.";
691 setp.text= "Set Q";
692 } else {
693 lab1.text= "Select Q.";
694 setp.text= "Set P";
695 }
696
697 } else if (mode) {
698 if (button_test(done,x,y)) {
699 if (done.text=="Cancel") {
700 if (!oldjP || !oldjQ) break;
701 jP= oldjP;
702 jQ= oldjQ;
703 } else {
704 if (kP==kQ) {
705 k= kP;
706 l= rez_range(min(lP,lQ):max(lP,lQ));
707 } else {
708 l= lP;
709 k= rez_range(min(kP,kQ):max(kP,kQ));
710 }
711 zt= rez_zt(k,l);
712 rt= rez_rt(k,l);
713 list= array([zt,rt], 20); /* keep last 20 for undo */
714 }
715 lab1.text= "Adjust line.";
716 setp.text= "Set P";
717 mode= 0;
718 } else if (abs(_rez_xvp-x)<=_rez_dxvp ||
719 abs(_rez_yvp-y)<=_rez_dyvp) {
720 j= rez_find(m(1), m(2));
721 if (numberof(_rez_center)>1) {
722 kc= (_rez_center-1)%kmax + 1;
723 lc= (_rez_center-1)/kmax + 1;
724 if (noneof(kc-kc(1))) kc= kc(1);
725 else if (noneof(lc-lc(1))) lc= lc(1);
726 if (mode==1 && jQ>0) {
727 kd= (jQ-1)%kmax + 1;
728 ld= (jQ-1)/kmax + 1;
729 if (numberof(kc)==1 && kc!=kd && anyof(lc==ld))
730 j= kc + (ld-1)*kmax;
731 else if (numberof(lc)==1 && lc!=ld && anyof(kc==kd))
732 j= kd + (lc-1)*kmax;
733 } else if (mode!=1 && jP>0) {
734 kd= (jP-1)%kmax + 1;
735 ld= (jP-1)/kmax + 1;
736 if (numberof(kc)==1 && kc!=kd && anyof(lc==ld))
737 j= kc + (ld-1)*kmax;
738 else if (numberof(lc)==1 && lc!=ld && anyof(kc==kd))
739 j= kd + (lc-1)*kmax;
740 }
741 }
742 if (j<1) {
743 rez_ding;
744 continue;
745 } else {
746 if (mode==1) jP= j;
747 else jQ= j;
748 kP= (jP-1)%kmax + 1;
749 lP= (jP-1)/kmax + 1;
750 kQ= (jQ-1)%kmax + 1;
751 lQ= (jQ-1)/kmax + 1;
752 }
753 } else {
754 rez_ding;
755 continue;
756 }
757
758 } else {
759 if (button_test(done,x,y)) break;
760 if (button_test(undo,x,y)) {
761 rez_zt(k,l)= list(,1,1);
762 rez_rt(k,l)= list(,2,1);
763 list(,,1:-1)= list(,,2:0);
764 } else if (button_test(setq,x,y)) {
765 oldjP= jP;
766 oldjQ= jQ;
767 lab1.text= "Select Q.";
768 mode= 2;
769 } else if (button_test(smth,x,y)) {
770 zt= rez_zt(k,l);
771 if (numberof(zt)>2) {
772 rt= rez_rt(k,l);
773 list(,,2:0)= list(,,1:-1);
774 list(,1,1)= zt;
775 list(,2,1)= rt;
776 zt(2:-1)= zt(zcen)(zcen);
777 rt(2:-1)= rt(zcen)(zcen);
778 rez_zt(k,l)= zt;
779 rez_rt(k,l)= rt;
780 }
781 } else if (button_test(eqsp,x,y)) {
782 zt= rez_zt(k,l);
783 n= numberof(zt);
784 if (n>2) {
785 rt= rez_rt(k,l);
786 list(,,2:0)= list(,,1:-1);
787 list(,1,1)= zt;
788 list(,2,1)= rt;
789 rez_zt(k,l)= span(zt(1), zt(0), n);
790 rez_rt(k,l)= span(rt(1), rt(0), n);
791 }
792 } else if (abs(_rez_xvp-x)<=_rez_dxvp ||
793 abs(_rez_yvp-y)<=_rez_dyvp) {
794 j= rez_find(m(1), m(2));
795 if (j<=min(jP,jQ) || j>=max(jP,jQ) ||
796 (kP==kQ && abs(j-jP)%kmax)) {
797 rez_ding;
798 continue;
799 } else {
800 zP= rez_zt(jP);
801 rP= rez_rt(jP);
802 zQ= rez_zt(jQ);
803 rQ= rez_rt(jQ);
804 zx= m(3)-zP;
805 rx= m(4)-rP;
806 za= zQ-zP;
807 ra= rQ-rP;
808 /* set sx to projection of new point onto PQ, normalized to
809 lie between 0 (at P) and 1 (at Q) */
810 sx= (za*zx+ra*rx)/abs(za,ra,1.e-35)^2;
811 if (sx>0. && sx<1.) {
812 zt= rez_zt(k,l);
813 rt= rez_rt(k,l);
814 list(,,2:0)= list(,,1:-1);
815 list(,1,1)= zt;
816 list(,2,1)= rt;
817 n= numberof(zt)-1; /* already guaranteed >1 */
818 if (kP==kQ) m= abs((j-1)/kmax + 1 - lP);
819 else m= abs((j-1)%kmax + 1 - kP);
820 m= 1./m;
821 r= rez_solve(1./sx, n*m)^m;
822 sa= spanl(1., r^(n-1), n)(cum);
823 sx= [0.0, sa(0)];
824 zt= interp([zP,zQ], sx, sa);
825 rt= interp([rP,rQ], sx, sa);
826 if (kP>kQ || lP>lQ) {
827 zt= zt(0:1:-1);
828 rt= rt(0:1:-1);
829 }
830 rez_zt(k,l)= zt;
831 rez_rt(k,l)= rt;
832 } else {
833 rez_ding;
834 continue;
835 }
836 }
837 } else {
838 rez_ding;
839 continue;
840 }
841 }
842 rez_plm, !mode, 1;
843 if (!mode || (jP && jQ && ((kQ==kP) ~ (lQ==lP)))) {
844 done.text= "OK";
845 done.dx= 0.020;
846 } else {
847 done.text= "Cancel";
848 done.dx= 0.033;
849 }
850 button_plot, done, lab1, zorp, sets, setp;
851 if (jP) plg, rez_rt(kP,lP), rez_zt(kP,lP),
852 marker='P', type=0, legend=string(0);
853 if (jQ) plg, rez_rt(kQ,lQ), rez_zt(kQ,lQ),
854 marker='Q', type=0, legend=string(0);
855 if (!mode) button_plot, undo, setq, drag, smth, eqsp;
856 else if (jP || jQ) {
857 text= jP? swrite(format="P=(%ld,%ld)",kP,lP) : "";
858 if (jQ) text+= swrite(format=" Q=(%ld,%ld)",kQ,lQ);
859 plt, text, 0.35, 0.375;
860 }
861 }
862
863 rez_plm, 1;
864 }
865
866 func rez_radj
867 /* DOCUMENT rez_radj
868 Adjust the points in a logical rectangle PQRS:
869
870 Click on [Set P] or [Set R] to set the endpoints of the segment.
871 When P and R have been set, click [OK]; this button will
872 read [Cancel] if P and R have the same K or the same L index.
873
874 Click on a point on any edge of PQRS (but not one of the corners)
875 to copy the spacings on that edge throughout the entire region.
876 All of the lines of the same type (K-line or L-line) as the edge
877 you clicked on will become straight lines.
878
879 Click on [Smooth] to smooth the points interior to PQRS.
880 Click on [Smooth 4] to perform the smooth operation four times.
881
882 Click on the [Undo] button to undo the previous adjustment; you can
883 undo up to 10 previous adjustments by successive [Undo] clicks.
884
885 When you are finished adjusting regions, click on [OK].
886
887 Click on [Zoom or Pan] to change the plot limits (see rez_zoom).
888
889 Click on [Set Styles] to change the line styles or colors (see
890 rez_style).
891
892 Hint:
893 You can select a center point as the second point during
894 rez_radj. When you do this, the K (or L) value of this second
895 point will be the same as that of the first point --
896 otherwise there is no way to distinguish among all of the
897 logical points at the center. The center point will be labeled
898 Q instead of R as usual, and you will need to choose a third
899 point (S) to complete the rectangle PQRS.
900
901 SEE ALSO: rez_drag, rez_ladj, rez_mesh, rez_zoom, rez_style
902 */
903 {
904 done= Button(text="OK",x=.203,y=.895,dx=.020,dy=.012);
905 undo= Button(text="Undo",x=.254,y=.895,dx=.025,dy=.012);
906 lab1= Button(text="Adjust region.",x=.344,y=.895,dx=.050,dy=.012,width=-1);
907 zorp= Button(text="Zoom or Pan",x=.464,y=.895,dx=.054,dy=.012);
908 sets= Button(text="Set Styles",x=.569,y=.895,dx=.045,dy=.012);
909
910 setp= Button(text="Set P",x=.208,y=.375,dx=.027,dy=.012);
911 setr= Button(text="Set R",x=.268,y=.375,dx=.027,dy=.012);
912 drag= Button(text="Click edge for EQ",x=.371,y=.375,
913 dx=.035,dy=.012,width=-1);
914 smth= Button(text="Smooth",x=.480,y=.375,dx=.035,dy=.012);
915 eqsp= Button(text="Smooth 4",x=.563,y=.375,dx=.041,dy=.012);
916
917 mode= 1;
918 jP= jR= jQ= oldjP= oldjR= 0;
919 rez_plm, 1;
920 kmax= dimsof(rez_rt)(2);
921 lab1.text= "Select P.";
922 setp.text= "Set R";
923 done.text= "Cancel";
924 done.dx= 0.033;
925 button_plot, done, lab1, zorp, sets, setp;
926
927 for (;;) {
928 m= mouse(1, 2, "");
929 if (is_void(m)) { rdline,prompt=""; continue; }
930 x= m(5);
931 y= m(6);
932 if (button_test(zorp,x,y)) {
933 rez_zoom;
934 } else if (button_test(sets,x,y)) {
935 rez_style;
936 } else if (button_test(setp,x,y)) {
937 mode= 1 + (setp.text!="Set P");
938 if (mode==1) {
939 lab1.text= "Select P.";
940 setp.text= "Set R";
941 } else {
942 lab1.text= "Select R.";
943 setp.text= "Set P";
944 }
945 jQ= 0;
946
947 } else if (mode) {
948 if (button_test(done,x,y)) {
949 if (done.text=="Cancel") {
950 if (!oldjP || !oldjR) break;
951 jP= oldjP;
952 jR= oldjR;
953 } else {
954 k0= min(kP,kR);
955 k1= max(kP,kR);
956 l0= min(lP,lR);
957 l1= max(lP,lR);
958 zt= rez_zt(k0:k1,l0:l1);
959 rt= rez_rt(k0:k1,l0:l1);
960 list= array([zt,rt], 10); /* keep last 10 for undo */
961 }
962 lab1.text= "Adjust region.";
963 setp.text= "Set P";
964 mode= jQ= 0;
965 } else if (abs(_rez_xvp-x)<=_rez_dxvp ||
966 abs(_rez_yvp-y)<=_rez_dyvp) {
967 j= rez_find(m(1), m(2));
968 mold= mode;
969 if (numberof(_rez_center)>1) {
970 if (mode==2 && jP>0) {
971 kc= (_rez_center-1)%kmax + 1;
972 lc= (_rez_center-1)/kmax + 1;
973 if (noneof(kc-kc(1))) kc= kc(1);
974 else if (noneof(lc-lc(1))) lc= lc(1);
975 kd= (jP-1)%kmax + 1;
976 ld= (jP-1)/kmax + 1;
977 if (numberof(kc)==1 && kc!=kd && anyof(lc==ld))
978 j= kc + (ld-1)*kmax;
979 else if (numberof(lc)==1 && lc!=ld && anyof(kc==kd))
980 j= kd + (lc-1)*kmax;
981 lab1.text= "Select S.";
982 mode= 3;
983 } else {
984 j= 0;
985 }
986 }
987 if (j<1) {
988 rez_ding;
989 continue;
990 } else {
991 if (mode==1) jP= j;
992 else if (mode==2) jR= j;
993 else if (mode!=mold) jQ= j;
994 else if (kP==kQ) jR= (j-1)%kmax + 1 + (lQ-1)*kmax;
995 else jR= kQ + ((j-1)/kmax)*kmax;
996 kP= (jP-1)%kmax + 1;
997 lP= (jP-1)/kmax + 1;
998 kR= (jR-1)%kmax + 1;
999 lR= (jR-1)/kmax + 1;
1000 kQ= (jQ-1)%kmax + 1;
1001 lQ= (jQ-1)/kmax + 1;
1002 }
1003 } else {
1004 rez_ding;
1005 continue;
1006 }
1007
1008 } else {
1009 if (button_test(done,x,y)) break;
1010 if (button_test(undo,x,y)) {
1011 rez_zt(k0:k1,l0:l1)= list(,,1,1);
1012 rez_rt(k0:k1,l0:l1)= list(,,2,1);
1013 list(,,,1:-1)= list(,,,2:0);
1014 } else if (button_test(setr,x,y)) {
1015 oldjP= jP;
1016 oldjR= jR;
1017 lab1.text= "Select R.";
1018 mode= 2;
1019 } else if (button_test(smth,x,y)) {
1020 zt= rez_zt(k0:k1,l0:l1);
1021 if (dimsof(zt)(2)>2 && dimsof(zt)(3)>2) {
1022 rt= rez_rt(k0:k1,l0:l1);
1023 list(,,,2:0)= list(,,,1:-1);
1024 list(,,1,1)= zt;
1025 list(,,2,1)= rt;
1026 zt(2:-1,2:-1)= zt(zcen,zcen)(zcen,zcen);
1027 rt(2:-1,2:-1)= rt(zcen,zcen)(zcen,zcen);
1028 rez_zt(k0:k1,l0:l1)= zt;
1029 rez_rt(k0:k1,l0:l1)= rt;
1030 }
1031 } else if (button_test(eqsp,x,y)) {
1032 zt= rez_zt(k0:k1,l0:l1);
1033 if (dimsof(zt)(2)>2 && dimsof(zt)(3)>2) {
1034 rt= rez_rt(k0:k1,l0:l1);
1035 list(,,,2:0)= list(,,,1:-1);
1036 list(,,1,1)= zt;
1037 list(,,2,1)= rt;
1038 for (ii=0 ; ii<4 ; ii++) {
1039 zt(2:-1,2:-1)= zt(zcen,zcen)(zcen,zcen);
1040 rt(2:-1,2:-1)= rt(zcen,zcen)(zcen,zcen);
1041 }
1042 rez_zt(k0:k1,l0:l1)= zt;
1043 rez_rt(k0:k1,l0:l1)= rt;
1044 }
1045 } else if (abs(_rez_xvp-x)<=_rez_dxvp ||
1046 abs(_rez_yvp-y)<=_rez_dyvp) {
1047 j= rez_find(m(1), m(2));
1048 kj= (j-1)%kmax + 1;
1049 lj= (j-1)/kmax + 1;
1050 inl= (lj>l0 && lj<l1);
1051 ink= (kj>k0 && kj<k1);
1052 zt= rez_zt(k0:k1,l0:l1);
1053 rt= rez_rt(k0:k1,l0:l1);
1054 if (j>0 && (kj==k0 || kj==k1) && inl) {
1055 list(,,,2:0)= list(,,,1:-1);
1056 list(,,1,1)= zt;
1057 list(,,2,1)= rt;
1058 ds= abs(zt(kj==k0,dif),rt(kj==k0,dif))(-,cum);
1059 ds/= ds(1,0);
1060 rez_zt(k0:k1,l0:l1)= zt(,1) + (zt(,0)-zt(,1))*ds
1061 rez_rt(k0:k1,l0:l1)= rt(,1) + (rt(,0)-rt(,1))*ds
1062 } else if (j>0 && (lj==l0 || lj==l1) && ink) {
1063 list(,,,2:0)= list(,,,1:-1);
1064 list(,,1,1)= zt;
1065 list(,,2,1)= rt;
1066 ds= abs(zt(dif,lj==l0),rt(dif,lj==l0))(cum);
1067 ds/= ds(0);
1068 rez_zt(k0:k1,l0:l1)= zt(1,-,) + (zt(0,-,)-zt(1,-,))*ds
1069 rez_rt(k0:k1,l0:l1)= rt(1,-,) + (rt(0,-,)-rt(1,-,))*ds
1070 } else {
1071 rez_ding;
1072 continue;
1073 }
1074 } else {
1075 rez_ding;
1076 continue;
1077 }
1078 }
1079 rez_plm, !mode, 1;
1080 if (!mode || (jP && jR && kR!=kP && lR!=lP)) {
1081 done.text= "OK";
1082 done.dx= 0.020;
1083 } else {
1084 done.text= "Cancel";
1085 done.dx= 0.033;
1086 }
1087 button_plot, done, lab1, zorp, sets, setp;
1088 if (jP) plg, rez_rt(kP,lP), rez_zt(kP,lP),
1089 marker='P', type=0, legend=string(0);
1090 if (jR) plg, rez_rt(kR,lR), rez_zt(kR,lR),
1091 marker='R', type=0, legend=string(0);
1092 if (jQ) plg, rez_rt(kQ,lQ), rez_zt(kQ,lQ),
1093 marker='Q', type=0, legend=string(0);
1094 if (done.text=="OK") {
1095 if (!jQ) plg, rez_rt(kP,lR), rez_zt(kP,lR),
1096 marker='Q', type=0, legend=string(0);
1097 plg, rez_rt(kR,lP), rez_zt(kR,lP),
1098 marker='S', type=0, legend=string(0);
1099 }
1100 if (!mode) button_plot, undo, setr, drag, smth, eqsp;
1101 else if (jP || jR) {
1102 text= jP? swrite(format="P=(%ld,%ld)",kP,lP) : "";
1103 if (jR) text+= swrite(format=" R=(%ld,%ld)",kR,lR);
1104 else if (jQ) text+= swrite(format=" Q=(%ld,%ld)",kQ,lQ);
1105 plt, text, 0.35, 0.375;
1106 }
1107 }
1108
1109 rez_plm, 1;
1110 }
1111
1112 _rez_zoom= 0n;
1113
1114 func rez_zoom
1115 /* DOCUMENT rez_zoom
1116 Change limits after setting rez_mesh.
1117
1118 There are two modes of operation:
1119 (1) P-mode:
1120 Click on a point to magnify or demagnify about that point.
1121 Drag the point to move it to a different position in the
1122 viewport. The left button zooms in (magnifies by 1.5), the
1123 right button zooms out (demagnifies by 1.5), and the middle
1124 button pans (no magnification change). If you click just
1125 below or just above the tick marks, only the x coordinate
1126 is changed; clicking just to the left or just to the right
1127 of the viewport changes only the y coordinate.
1128 (2) R-mode:
1129 Left drag out a rectangle to set the limits to that rectangle.
1130 Right drag out a rectangle to cram the entire current viewport
1131 into that rectangle (an analog to zooming out).
1132 Middle drag to pan as in P-mode (the rubber band rectangle is
1133 meaningless in this case).
1134
1135 Click the [R-mode] (or [P-mode]) button to change modes.
1136
1137 Click the [OK] button when you are satisfied with the limits.
1138
1139 Click the [Undo] button to remove the effect of the previous
1140 zoom-click. Up to 100 successive undo operations are allowed.
1141
1142 Click the [Polar] button to toggle polar coordinates. The
1143 vertical axis will be theta, and the horizontal axis radius.
1144 The polar coordinate origin will be at (zt,rt) = (0,0).
1145
1146 Click the [Next], [Prev], or [First] buttons to focus in on
1147 zones which are bowtied or chevroned. These zones are marked
1148 by a B or a C, respectively (if rez_mark is set).
1149
1150 SEE ALSO: rez_mesh
1151 */
1152 {
1153 done= Button(text="OK",x=.203,y=.895,dx=.020,dy=.012);
1154 undo= Button(text="Undo",x=.254,y=.895,dx=.025,dy=.012);
1155 lab2= Button(text="Left=in Middle=pan Right=out",
1156 x=.413,y=.895,dx=.128,dy=.012,width=-1);
1157 mode= Button(text=(_rez_zoom?"P-Mode":"R-Mode"),
1158 x=.584,y=.895,dx=.037,dy=.012);
1159
1160 full= Button(text="Full Mesh",x=.230,y=.375,dx=.046,dy=.012);
1161 polar= Button(text="Polar",x=.307,y=.375,dx=.025,dy=.012);
1162 lab3= Button(text="Go To Bowtie:",
1163 x=.402,y=.375,dx=.040,dy=.012,width=-1);
1164 next= Button(text="Next",x=.486,y=.375,dx=.025,dy=.012);
1165 prev= Button(text="Prev",x=.536,y=.375,dx=.025,dy=.012);
1166 first= Button(text="First",x=.587,y=.375,dx=.026,dy=.012);
1167
1168 rez_plm, 1;
1169 button_plot, done, undo, lab2, mode, full, polar, lab3, next, prev, first;
1170
1171 list= array(0.0, 5, 100); /* keep last 100 limits for undo */
1172 len= 0;
1173 for (;;) {
1174 m= mouse(1, _rez_zoom, "");
1175 if (is_void(m)) { rdline,prompt=""; continue; }
1176 x= m(5);
1177 y= m(6);
1178 if (button_test(done,x,y)) break;
1179 if (button_test(undo,x,y)) {
1180 if (len) {
1181 limits, list(,1);
1182 list(,1:-1)= list(,2:0);
1183 len--;
1184 } else {
1185 rez_ding;
1186 continue;
1187 }
1188 } else if (button_test(mode,x,y)) {
1189 _rez_zoom= !_rez_zoom;
1190 mode.text= (_rez_zoom?"P-Mode":"R-Mode");
1191 } else if (button_test(full,x,y)) {
1192 limits; redraw;
1193 continue;
1194 } else if (button_test(polar,x,y)) {
1195 rez_toggle;
1196 limits;
1197 } else if (button_test(next,x,y)) {
1198 rez_next; redraw;
1199 continue;
1200 } else if (button_test(prev,x,y)) {
1201 rez_prev; redraw;
1202 continue;
1203 } else if (button_test(first,x,y)) {
1204 rez_next, 1; redraw;
1205 continue;
1206 } else if (abs(_rez_xvp-x)<=_rez_dxvp ||
1207 abs(_rez_yvp-y)<=_rez_dyvp) {
1208 x= m(1);
1209 y= m(2);
1210 x1= m(3);
1211 y1= m(4);
1212 button= long(m(10));
1213 lims= limits();
1214 if (!_rez_zoom || button==2) { /* point mode */
1215 if (button==1) f= 1.5;
1216 else if (button==2) f= 1.0;
1217 else f= 1.0/1.5;
1218 x0= x - (x1-lims(1))/f;
1219 x1= x - (x1-lims(2))/f;
1220 y0= y - (y1-lims(3))/f;
1221 y1= y - (y1-lims(4))/f;
1222 if (x!=lims(1) && x!=lims(2)) {
1223 if (y!=lims(3) && y!=lims(4)) limits, x0,x1,y0,y1;
1224 else limits, x0,x1;
1225 } else {
1226 if (y!=lims(3) && y!=lims(4)) limits, ,,y0,y1;
1227 else limits, x0,x1,y0,y1;
1228 }
1229 list(,2:0)= list(,1:-1);
1230 list(,1)= lims;
1231 len++;
1232 } else if (x!=x1 && y!=y1) { /* rectangle mode */
1233 x0= min(x,x1);
1234 x1= max(x,x1);
1235 y0= min(y,y1);
1236 y1= max(y,y1);
1237 if (button!=1) {
1238 f= (lims(2)-lims(1))/(x1-x0);
1239 x0= lims(1) - f*(x0-lims(1));
1240 x1= lims(2) + f*(lims(2)-x1);
1241 f= (lims(4)-lims(3))/(y1-y0);
1242 y0= lims(3) - f*(y0-lims(3));
1243 y1= lims(4) + f*(lims(4)-y1);
1244 }
1245 limits, x0,x1,y0,y1;
1246 list(,2:0)= list(,1:-1);
1247 list(,1)= lims;
1248 len++;
1249 } else {
1250 rez_ding;
1251 continue;
1252 }
1253 }
1254 rez_plm, 0;
1255 button_plot, done, undo, lab2, mode, full, polar, lab3, next, prev, first;
1256 }
1257 }
1258
1259 func rez_style
1260 {
1261 done= Button(text="OK",x=.203,y=.895,dx=.020,dy=.012);
1262 klin= Button(text="K-line",x=.290,y=.895,dx=.038,dy=.012,width=6.);
1263 llin= Button(text="L-line",x=.366,y=.895,dx=.038,dy=.012);
1264 type= Button(text="Type",x=.476,y=.895,dx=.025,dy=.012,width=6.);
1265 wdth= Button(text="Width",x=.530,y=.895,dx=.029,dy=.012);
1266 colr= Button(text="Color",x=.586,y=.895,dx=.027,dy=.012);
1267
1268 bar1= ["1", "2", "3", "4", "5", "6", "7", "8"];
1269 bar2= ["bg", "fg", "blk", "wht",
1270 "red", "grn", "blu", "cyn", "mag", "yel"];
1271 bar= array(Button, 10);
1272 bar.dx= bardx= .022;
1273 bar.x= barx= .644;
1274 bar.dy= bardy= .012;
1275 bar.y= .895-(indgen(10)-1)*2.*bardy;
1276 bary= avg(bar.y);
1277
1278 bar(1:5).text= bar1(1:5);
1279 barn= 5;
1280 bar(rez_kstyle(1)).width= 6.;
1281 change= 1;
1282
1283 for (;;) {
1284 if (change) {
1285 i= where(bar.width)(1);
1286 if (type.width) {
1287 if (klin.width) rez_kstyle(1)= i;
1288 else rez_lstyle(1)= i;
1289 } else if (wdth.width) {
1290 if (klin.width) rez_kstyle(2)= i;
1291 else rez_lstyle(2)= i;
1292 } else if (colr.width) {
1293 if (klin.width) rez_kstyle(3)= -i;
1294 else rez_lstyle(3)= -i;
1295 }
1296 rez_plm, 0;
1297 button_plot, done, klin, llin, type, wdth, colr, bar(1:barn);
1298 change= 0;
1299 }
1300 m= mouse(0, _rez_zoom, "");
1301 if (is_void(m)) { rdline,prompt=""; continue; }
1302 x= m(5);
1303 y= m(6);
1304 if (button_test(done,x,y)) break;
1305 if (button_test(klin,x,y)) {
1306 if (klin.width) continue;
1307 klin.width= 6.;
1308 llin.width= 0.;
1309 bar.width= 0.;
1310 if (type.width) bar(rez_kstyle(1)).width= 6.;
1311 else if (wdth.width) bar(rez_kstyle(2)).width= 6.;
1312 else if (colr.width) bar(-rez_kstyle(3)).width= 6.;
1313 } else if (button_test(llin,x,y)) {
1314 if (llin.width) continue;
1315 llin.width= 6.;
1316 klin.width= 0.;
1317 bar.width= 0.;
1318 if (type.width) bar(rez_lstyle(1)).width= 6.;
1319 else if (wdth.width) bar(rez_lstyle(2)).width= 6.;
1320 else if (colr.width) bar(-rez_lstyle(3)).width= 6.;
1321 } else if (button_test(type,x,y)) {
1322 if (type.width) continue;
1323 type.width= 6.;
1324 wdth.width= colr.width= 0.;
1325 bar(1:5).text= bar1(1:5);
1326 barn= 5;
1327 bar.width= 0.;
1328 if (klin.width) bar(rez_kstyle(1)).width= 6.;
1329 else bar(rez_lstyle(1)).width= 6.;
1330 } else if (button_test(wdth,x,y)) {
1331 if (wdth.width) continue;
1332 wdth.width= 6.;
1333 type.width= colr.width= 0.;
1334 bar(1:8).text= bar1;
1335 barn= 8;
1336 bar.width= 0.;
1337 if (klin.width) bar(rez_kstyle(2)).width= 6.;
1338 else bar(rez_lstyle(2)).width= 6.;
1339 } else if (button_test(colr,x,y)) {
1340 if (colr.width) continue;
1341 colr.width= 6.;
1342 type.width= wdth.width= 0.;
1343 bar.text= bar2;
1344 barn= 10;
1345 bar.width= 0.;
1346 if (klin.width) bar(-rez_kstyle(3)).width= 6.;
1347 else bar(-rez_lstyle(3)).width= 6.;
1348 } else if (abs(barx-x)<bardx && abs(bary-y)<2.*barn*bardy) {
1349 i= long((bar(1).y+bardy - y)/(2.0*bardy)) + 1;
1350 if (i>0 && i<=barn) {
1351 bar.width= 0.;
1352 bar(i).width= 6.;
1353 } else {
1354 rez_ding;
1355 continue;
1356 }
1357 } else {
1358 rez_ding;
1359 continue;
1360 }
1361 change= 1;
1362 }
1363 }
1364
1365 extern rez_qrt, rez_qzt, rez_qireg;
1366 /* DOCUMENT rez_qrt, rez_qzt, rez_qireg
1367 are the names of the mesh variables for rez_mesh, "rt", "zt", and
1368 "ireg" by default. Note that ireg is optional.
1369 */
1370 rez_qzt= "zt";
1371 rez_qrt= "rt";
1372 rez_qireg= "ireg";
1373
1374 func rez_mesh(rt, zt, ireg, all=, quiet=)
1375 /* DOCUMENT rez_mesh, rt, zt, ireg
1376 or rez_mesh, rt, zt
1377 or rez_mesh, zfile
1378 set mesh for rez_... commands. If ZFILE is specified, it must be a
1379 binary file containing variables RT, ZT, and (optionally) IREG.
1380 SEE ALSO: rez_all, rez_adjust_mesh
1381 */
1382 {
1383 extern rez_rt0, rez_zt0, rez_ireg0, rez_rt, rez_zt, rez_ireg;
1384 extern rez_mapi;
1385
1386 if (is_stream(rt)) {
1387 f= rt;
1388 vars= get_vars(f);
1389 ireg= rez_getvar(f,vars, rez_qireg);
1390 zt= rez_getvar(f,vars, rez_qzt);
1391 rt= rez_getvar(f,vars, rez_qrt);
1392 }
1393 if (is_void(ireg)) {
1394 ireg= array(1, dimsof(rt));
1395 ireg(1,)= 0;
1396 ireg(,1)= 0;
1397 }
1398
1399 rez_rt0= rez_rt= rt;
1400 rez_zt0= rez_zt= zt;
1401 rez_ireg0= rez_ireg= ireg;
1402 if (is_void(zt) || is_void(rt)) return;
1403 rez_ptexist;
1404
1405 rez_mapi= 0;
1406 if (!quiet) nbow, rez_rt, rez_zt, rez_ireg, all=all;
1407
1408 rez_plm, 1;
1409 }
1410
rez_next(which)1411 func rez_next(which)
1412 /* DOCUMENT rez_next
1413 zoom in on next bowtied (or chevroned) zone (after rez_mesh).
1414 With numeric argument, zooms to that bowtie (or chevron). With
1415 numeric argument 0, zooms to current bowtie (or chevron).
1416 SEE ALSO: rez_prev, rez_mark, rez_drag
1417 */
1418 {
1419 list= where(rez_map==0);
1420 n= where(rez_map==1);
1421 if (!numberof(list)) list= [];
1422 if (!numberof(n)) n= [];
1423 list= grow(list,n);
1424 n= numberof(list);
1425 if (is_void(which)) which= rez_mapi+1;
1426 else if (!which) which= rez_mapi? rez_mapi : 1;
1427 else if (which<0) which= rez_mapi>1? rez_mapi-1 : n+1;
1428 if (!n || which>n) { rez_ding; return; }
1429 local rr, zz;
1430 rez_getrz, list(which);
1431 rn= min(rr); rx= max(rr);
1432 zn= min(zz); zx= max(zz);
1433 rr= rx-rn;
1434 zz= zx-zn;
1435 zn-= 0.3*zz;
1436 zx+= 0.3*zz;
1437 rn-= 0.3*rr;
1438 rx+= 0.3*rr;
1439 limits, zn, zx, rn, rx;
1440 rez_mapi= which;
1441 }
1442
1443 func rez_prev
1444 /* DOCUMENT rez_prev
1445 zoom in on previous bowtied (or chevroned) zone (after rez_mesh).
1446 SEE ALSO: rez_next, rez_mark, rez_drag
1447 */
1448 {
1449 rez_next, -1;
1450 }
1451
rez_getrz(zlist)1452 func rez_getrz(zlist)
1453 {
1454 extern rr, zz; /* 2-by-2-by-dimsof(zlist) result */
1455 if (!numberof(zlist)) {
1456 rr= zz= [];
1457 return;
1458 }
1459 dims= dimsof(rez_rt);
1460 kmax= dims(2);
1461 klist= (zlist-1)%(kmax-1);
1462 llist= (zlist-1)/(kmax-1);
1463 list= llist*kmax + klist + 1; /* lower left corner index */
1464 rr= zz= array(0.0, 2, 2, dimsof(list));
1465 rr(1,1,..)= rez_rt(list);
1466 zz(1,1,..)= rez_zt(list);
1467 rr(2,1,..)= rez_rt(list+1);
1468 zz(2,1,..)= rez_zt(list+1);
1469 rr(1,2,..)= rez_rt(list+kmax);
1470 zz(1,2,..)= rez_zt(list+kmax);
1471 rr(2,2,..)= rez_rt(list+kmax+1);
1472 zz(2,2,..)= rez_zt(list+kmax+1);
1473 }
1474
1475 func rez_ptexist
1476 {
1477 extern rez_ptx, rez_ptlist, rez_ireg;
1478 rez_ireg(1,)= 0;
1479 rez_ireg(,1)= 0;
1480 d= dimsof(rez_ireg);
1481 ix= d(2);
1482 jx= d(3);
1483 n= numberof(rez_ireg);
1484 ireg= array(0, n+ix+1);
1485 ireg(1:n)= rez_ireg(*);
1486 rez_ptx= array(0, dimsof(rez_ireg));
1487 rez_ptx(*)=
1488 (ireg(1:n) | ireg(2:n+1) | ireg(ix+1:n+ix) | ireg(ix+2:n+ix+1));
1489 rez_ptlist= where(rez_ptx);
1490 }
1491
1492 extern _rez_center;
1493
rez_find(x,y)1494 func rez_find(x, y)
1495 {
1496 extern _rez_center;
1497 d= abs(rez_zt-x, rez_rt-y)(rez_ptlist);
1498 j= d(mnx);
1499 d0= d(j);
1500 j0= rez_ptlist(j);
1501 j= where(!(d-d0)); /* detect center points */
1502 if (numberof(j)>1) _rez_center= rez_ptlist(j);
1503 else _rez_center= [];
1504 return j0;
1505 }
1506
rez_getvar(f,vars,name)1507 func rez_getvar(f, vars, name)
1508 {
1509 v= vars(2);
1510 if (v && anyof(*v == name)) return get_member(f,name);
1511 v= vars(1);
1512 if (v && anyof(*v == name)) return get_member(f,name);
1513 return [];
1514 }
1515
rez_range(x)1516 func rez_range(x) { return x; } /* parser quirk */
1517
1518 func rez_ding
1519 {
1520 write, format="%s", "\a\a";
1521 }
1522
rez_solve(ss,nn)1523 func rez_solve(ss, nn)
1524 /* xxDOCUMENT adapted from gseries_r(s, n) in series.i
1525 returns the ratio r of the finite geometric series, given the sum s:
1526 1 + r + r^2 + r^3 + ... + r^(nn-1) = ss,
1527 or (r^nn-1)/(r-1) = ss
1528
1529 Altered to solve only nn>0.0, but allows any real nn.
1530 */
1531 {
1532 /* compute an approximate result which has exact values and
1533 derivatives at s==1, s==n, and s->infinity --
1534 different approximations apply for s>n and s<n */
1535 if (nn==2) return ss-1.0;
1536 if (ss>nn) {
1537 pow= 1.0/(nn-1.0);
1538 npow= nn^pow - 1.0;
1539 n2r= 1.0/(nn-2.0);
1540 A= (2.0-nn*npow)*n2r;
1541 B= (2.0*npow-nn*pow)*nn*n2r;
1542 r= ss^pow - pow + A*(nn/ss)^pow + B/ss;
1543 } else {
1544 sn= (ss-1.0)/(nn-1.0);
1545 n2r= 1.0/(nn*nn);
1546 r= 1.0 - 1.0/ss + n2r*sn*sn*(nn+1.0 - sn);
1547 }
1548
1549 /* Polish the approximation using Newton-Raphson iterations. */
1550 if (ss!=nn) {
1551 for (;;) {
1552 rr= r-1.0;
1553 rn= r^(nn-1);
1554 rrss= rr*ss;
1555 delta= rrss - (r*rn-1.0);
1556 if (abs(delta)<=1.e-9*abs(rrss)) break;
1557 r+= delta/(nn*rn-ss);
1558 }
1559 /* try to get it to machine precision */
1560 if (delta) r+= delta/(nn*rn-ss);
1561 }
1562
1563 return r;
1564 }
1565
1566 func rez_test
1567 {
1568 extern rez_rt, rez_zt;
1569 x= span(0,1,10)(,-:1:7); y= span(0,.5,7)(-:1:10,);
1570 rez_mesh, x+y, x-y+.5;
1571 }
1572
1573 if (!is_void(rez_load_hook)) include, rez_load_hook;
1574