tomwalters@0
|
1 /*
|
tomwalters@0
|
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
|
tomwalters@0
|
3 ===========================================================================
|
tomwalters@0
|
4
|
tomwalters@0
|
5 Permission to use, copy, modify, and distribute this software without fee
|
tomwalters@0
|
6 is hereby granted for research purposes, provided that this copyright
|
tomwalters@0
|
7 notice appears in all copies and in all supporting documentation, and that
|
tomwalters@0
|
8 the software is not redistributed for any fee (except for a nominal shipping
|
tomwalters@0
|
9 charge). Anyone wanting to incorporate all or part of this software in a
|
tomwalters@0
|
10 commercial product must obtain a license from the Medical Research Council.
|
tomwalters@0
|
11
|
tomwalters@0
|
12 The MRC makes no representations about the suitability of this
|
tomwalters@0
|
13 software for any purpose. It is provided "as is" without express or implied
|
tomwalters@0
|
14 warranty.
|
tomwalters@0
|
15
|
tomwalters@0
|
16 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
tomwalters@0
|
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
|
tomwalters@0
|
18 A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
|
tomwalters@0
|
19 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
tomwalters@0
|
20 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
tomwalters@0
|
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
tomwalters@0
|
22 */
|
tomwalters@0
|
23
|
tomwalters@0
|
24 /*
|
tomwalters@0
|
25 spiral.c
|
tomwalters@0
|
26 ========
|
tomwalters@0
|
27
|
tomwalters@0
|
28 Tap SAI frames and draw each one as a spiral in the given window.
|
tomwalters@0
|
29 */
|
tomwalters@0
|
30
|
tomwalters@0
|
31 /*
|
tomwalters@0
|
32 Modifications made to the routines draw_spiral, map_ribbon, map_spiral
|
tomwalters@0
|
33 so that the nwidth section of the SAI image is taken into account while
|
tomwalters@0
|
34 doing the calculations, (in image.c, doColumn()) and while plotting,
|
tomwalters@0
|
35 only the positive section of the time axis is drawn.
|
tomwalters@0
|
36 Added a new field "nwid" in the _draw_state object.
|
tomwalters@0
|
37 17 March, 1995. A Jay Datta
|
tomwalters@0
|
38 */
|
tomwalters@0
|
39
|
tomwalters@0
|
40 #include <math.h>
|
tomwalters@0
|
41 #include <stdio.h>
|
tomwalters@0
|
42
|
tomwalters@0
|
43 #include "windows.h"
|
tomwalters@0
|
44 #include "stitch.h"
|
tomwalters@0
|
45 #include "source.h"
|
tomwalters@0
|
46 #include "draw.h"
|
tomwalters@0
|
47 #include "ops.h"
|
tomwalters@0
|
48 #include "spiral.h"
|
tomwalters@0
|
49
|
tomwalters@0
|
50 #ifndef lint
|
tomwalters@0
|
51 static char *sccs_id = "@(#)spiral.c 1.9 Mike Allerhand (MRC-APU) 6/1/91" ;
|
tomwalters@0
|
52 #endif
|
tomwalters@0
|
53
|
tomwalters@0
|
54 /****************************************************************************
|
tomwalters@0
|
55 * Misc definitions
|
tomwalters@0
|
56 ****************************************************************************/
|
tomwalters@0
|
57 #define TWOPI 6.28318530717
|
tomwalters@0
|
58 #define log2(x) (log((double)x)/log(2.0))
|
tomwalters@0
|
59
|
tomwalters@0
|
60 /****************************************************************************
|
tomwalters@0
|
61 * Model parameters.
|
tomwalters@0
|
62 * Defaults:
|
tomwalters@0
|
63 * form_spl = 'arch'
|
tomwalters@0
|
64 * dotsize_spl = 2
|
tomwalters@0
|
65 * axis_spl = off
|
tomwalters@0
|
66 * zero_spl = 4.072
|
tomwalters@0
|
67 * dotthresh_spl = 50
|
tomwalters@0
|
68 ****************************************************************************/
|
tomwalters@0
|
69 int frameheight, framewidth, nwid; /* Dimensions of each sai */
|
tomwalters@0
|
70
|
tomwalters@0
|
71 char form_spl = 'A' ; /* Form of spiral, 'A' or 'L' */
|
tomwalters@0
|
72 int dotsize_spl = 2 ; /* Dotsize in pixels */
|
tomwalters@0
|
73 int axis_spl = 0 ; /* Flag for spiral axis */
|
tomwalters@0
|
74 double zero_spl = 4.072 ; /* For rotation and circuit removal */
|
tomwalters@0
|
75 int dotthresh_spl = 25 ; /* Min peak height */
|
tomwalters@0
|
76
|
tomwalters@0
|
77 /*=================== COORDINATE SYSTEM OF THE DATA =======================*/
|
tomwalters@0
|
78
|
tomwalters@0
|
79 /****************************************************************************
|
tomwalters@0
|
80 * Size and location, (program arguments), of calibrated box, in
|
tomwalters@0
|
81 * coord system of the data.
|
tomwalters@0
|
82 * range = range or size of both axes, (ie. "magnification" of plot).
|
tomwalters@0
|
83 * xorg,yorg = real plot coordinates at centre of screen.
|
tomwalters@0
|
84 ****************************************************************************/
|
tomwalters@0
|
85 static float range;
|
tomwalters@0
|
86 static float xorg;
|
tomwalters@0
|
87 static float yorg;
|
tomwalters@0
|
88
|
tomwalters@0
|
89 /****************************************************************************
|
tomwalters@0
|
90 * Limits of calibrated box in coord system of the data.
|
tomwalters@0
|
91 ****************************************************************************/
|
tomwalters@0
|
92 static float Xd0, Yd0; /* Bottom-left corner */
|
tomwalters@0
|
93 static float Xd1, Yd1; /* Top-right corner */
|
tomwalters@0
|
94
|
tomwalters@0
|
95
|
tomwalters@0
|
96 /*===================== PIXEL COORDINATE SYSTEM ==========================*/
|
tomwalters@0
|
97
|
tomwalters@0
|
98 /****************************************************************************
|
tomwalters@0
|
99 * Dimensions of window (box plus border) in pixel coord system.
|
tomwalters@0
|
100 ****************************************************************************/
|
tomwalters@0
|
101 static int width,height;
|
tomwalters@0
|
102 static int border; /* border = min(width,height) / 6; */
|
tomwalters@0
|
103
|
tomwalters@0
|
104 /****************************************************************************
|
tomwalters@0
|
105 * Limits of on-screen calibrated box in pixel coord system.
|
tomwalters@0
|
106 ****************************************************************************/
|
tomwalters@0
|
107 static int Xp0, Yp0; /* Bottom-left corner (border, height-border) */
|
tomwalters@0
|
108 static int Xp1, Yp1; /* Top-right corner (width-border, border) */
|
tomwalters@0
|
109
|
tomwalters@0
|
110 /****************************************************************************
|
tomwalters@0
|
111 * Dimensions of calibrated box in pixel coord system
|
tomwalters@0
|
112 ****************************************************************************/
|
tomwalters@0
|
113 static int Wb; /* Box width Wb = Xp1-Xp0 */
|
tomwalters@0
|
114 static int Hb; /* Box height Hb = Yp0-Yp1 */
|
tomwalters@0
|
115
|
tomwalters@0
|
116 /****************************************************************************
|
tomwalters@0
|
117 * The parameters for the calibrated box in the pixel coord system are
|
tomwalters@0
|
118 * initialized for a given window size (width, height, in pixels),
|
tomwalters@0
|
119 * as follows:
|
tomwalters@0
|
120 *
|
tomwalters@0
|
121 * border = min(width,height) / 6;
|
tomwalters@0
|
122 * Xp0 = border;
|
tomwalters@0
|
123 * Xp1 = width - border;
|
tomwalters@0
|
124 * Yp0 = border;
|
tomwalters@0
|
125 * Yp1 = height - border;
|
tomwalters@0
|
126 * Wb = Xp1-Xp0;
|
tomwalters@0
|
127 * Hb = Yp1-Yp0;
|
tomwalters@0
|
128 ****************************************************************************/
|
tomwalters@0
|
129
|
tomwalters@0
|
130 /*================= COORDINATE SYSTEM TRANSFORMATIONS =====================*/
|
tomwalters@0
|
131
|
tomwalters@0
|
132 /****************************************************************************
|
tomwalters@0
|
133 * Transformations from coord system of the data to pixel coord system.
|
tomwalters@0
|
134 * For example, if the origin in the data coord system is (0,0), then
|
tomwalters@0
|
135 * the origin in the pixel coord system is (px(0),py(0)).
|
tomwalters@0
|
136 ****************************************************************************/
|
tomwalters@0
|
137 #define px(x) ((int)(Xp0+Wb/2+(x-xorg)*(Wb/range)))
|
tomwalters@0
|
138 #define py(y) ((int)(Yp0+Hb/2+(y-yorg)*(Hb/range)))
|
tomwalters@0
|
139
|
tomwalters@0
|
140 /****************************************************************************
|
tomwalters@0
|
141 * Screen Position (in pixel coord system): test position is within box.
|
tomwalters@0
|
142 ****************************************************************************/
|
tomwalters@0
|
143 #define Xinbox(x) ((Xp0<=x && x<=Xp1) ? 1 : 0)
|
tomwalters@0
|
144 #define Yinbox(y) ((Yp0<=y && y<=Yp1) ? 1 : 0)
|
tomwalters@0
|
145 #define inbox(x,y) ((Xinbox(x) && Yinbox(y)) ? 1 : 0)
|
tomwalters@0
|
146
|
tomwalters@0
|
147
|
tomwalters@0
|
148
|
tomwalters@0
|
149
|
tomwalters@0
|
150 /****************************************************************************
|
tomwalters@0
|
151 * This routine is called once per SAI frame. The SAI data is in array "frame".
|
tomwalters@0
|
152 * The SAI frame is formatted row-wise, starting with the lowest-frequency row.
|
tomwalters@0
|
153 * The state structure is:
|
tomwalters@0
|
154 * struct _draw_state {
|
tomwalters@0
|
155 * Source source;
|
tomwalters@0
|
156 * WindowObject window;
|
tomwalters@0
|
157 * int min, max;
|
tomwalters@0
|
158 * int framewidth, frameheight; dimensions of the SAI
|
tomwalters@0
|
159 * int nwid;
|
tomwalters@0
|
160 * long frames;
|
tomwalters@0
|
161 * long framenumber;
|
tomwalters@0
|
162 * void (*interceptor)(); function which stores window for replay
|
tomwalters@0
|
163 * void (*drawer)(); drawing function
|
tomwalters@0
|
164 * };
|
tomwalters@0
|
165 *
|
tomwalters@0
|
166 * This struct is defined in stitch/draw.h
|
tomwalters@0
|
167 * It is initialized by routine "SourceDraw" in stitch/draw.c, which is called
|
tomwalters@0
|
168 * from gen.c. Note that this takes place after the SaiEntry routine has been
|
tomwalters@0
|
169 * called, so the sai dimensions set there will apply.
|
tomwalters@0
|
170 *
|
tomwalters@0
|
171 ****************************************************************************/
|
tomwalters@0
|
172 void draw_spiral( state, image )
|
tomwalters@0
|
173 struct _draw_state *state ;
|
tomwalters@0
|
174 short *image ;
|
tomwalters@0
|
175 {
|
tomwalters@0
|
176 static int first=1; /* flag for first-call of this routine */
|
tomwalters@0
|
177
|
tomwalters@0
|
178 /* Coordinate arrays for axis and spiral points */
|
tomwalters@0
|
179 static short *Xaxis;
|
tomwalters@0
|
180 static short *Yaxis;
|
tomwalters@0
|
181 static int naxis = 0; /* number of points plotted along spiral axis */
|
tomwalters@0
|
182 /* (naxis = (100 * nsamples) +1) */
|
tomwalters@0
|
183 static short *Xspiral;
|
tomwalters@0
|
184 static short *Yspiral;
|
tomwalters@0
|
185 int npoints = 0; /* number of samples in pulse ribbon and spiral */
|
tomwalters@0
|
186
|
tomwalters@0
|
187 static short *Xdot;
|
tomwalters@0
|
188 static short *Ydot;
|
tomwalters@0
|
189
|
tomwalters@0
|
190 static short *frame ;
|
tomwalters@0
|
191
|
tomwalters@0
|
192 frameheight = state->frameheight;
|
tomwalters@0
|
193 framewidth= (state->framewidth)+(state->nwid); /* -nwid */
|
tomwalters@0
|
194 /* fprintf(stderr, "THE NWID VALUE is %d\n", state->nwid); */
|
tomwalters@0
|
195 nwid=-state->nwid;
|
tomwalters@0
|
196 /* fprintf(stderr, "framewidth=%d, frameheight=%d\n", frameheight, framewidth); */
|
tomwalters@0
|
197 /* Initialize parameters of pixel coord system (see spiral.h) */
|
tomwalters@0
|
198 width = Width( state->window ) ;
|
tomwalters@0
|
199 height = Height( state->window ) ;
|
tomwalters@0
|
200
|
tomwalters@0
|
201 border = 0;
|
tomwalters@0
|
202
|
tomwalters@0
|
203 Xp0 = border;
|
tomwalters@0
|
204 Xp1 = width - border;
|
tomwalters@0
|
205 Yp0 = border;
|
tomwalters@0
|
206 Yp1 = height - border;
|
tomwalters@0
|
207 Wb = Xp1-Xp0;
|
tomwalters@0
|
208 Hb = Yp1-Yp0;
|
tomwalters@0
|
209
|
tomwalters@0
|
210 /* Initialize parameters of data coord system */
|
tomwalters@0
|
211 if (form_spl == 'A') range = 2 * (TWOPI * log2((double)(framewidth+nwid)) - TWOPI * zero_spl);
|
tomwalters@0
|
212 if (form_spl == 'L') range = 2 * (framewidth+nwid);
|
tomwalters@0
|
213 xorg = 0;
|
tomwalters@0
|
214 yorg = 0;
|
tomwalters@0
|
215
|
tomwalters@0
|
216 /* Allocate space (first-time call only). */
|
tomwalters@0
|
217 if (first) {
|
tomwalters@0
|
218 first = 0;
|
tomwalters@0
|
219 frame = NewArray(short, frameheight*(framewidth+nwid), "frame spiral.c" );
|
tomwalters@0
|
220 if (axis_spl) {
|
tomwalters@0
|
221 /* Allocate space and compute (X,Y) coords for spiral axis. */
|
tomwalters@0
|
222 /* Resolution of points on axis is 100 times greater, so that */
|
tomwalters@0
|
223 /* inner circuits look smooth. Add 1 as time starts from zero.*/
|
tomwalters@0
|
224 naxis = (100*framewidth+nwid)+1;
|
tomwalters@0
|
225 Xaxis = NewArray(short, naxis, "Xaxis, spiral.c" );
|
tomwalters@0
|
226 Yaxis = NewArray(short, naxis, "Yaxis, spiral.c" );
|
tomwalters@0
|
227 naxis = gen_axis(Xaxis,Yaxis,naxis,form_spl,zero_spl);
|
tomwalters@0
|
228 }
|
tomwalters@0
|
229 if (dotsize_spl) {
|
tomwalters@0
|
230 /* Allocate space for coords of spiral points.*/
|
tomwalters@0
|
231 Xspiral = NewArray(short, frameheight * framewidth+nwid, "Xspiral spiral.c" );
|
tomwalters@0
|
232 Yspiral = NewArray(short, frameheight * framewidth+nwid, "Yspiral spiral.c" );
|
tomwalters@0
|
233 Xdot = NewArray(short, frameheight * framewidth+nwid, "Xdot spiral.c" );
|
tomwalters@0
|
234 Ydot = NewArray(short, frameheight * framewidth+nwid, "Ydot spiral.c" );
|
tomwalters@0
|
235 }
|
tomwalters@0
|
236 }
|
tomwalters@0
|
237
|
tomwalters@0
|
238 CopyArray( image, frame, (framewidth+nwid)*frameheight ) ;
|
tomwalters@0
|
239
|
tomwalters@0
|
240 /* Map one SAI frame onto a pulse ribbon, and return the number of 1's */
|
tomwalters@0
|
241 npoints = map_ribbon(frame,dotthresh_spl);
|
tomwalters@0
|
242
|
tomwalters@0
|
243 /* Map 1's in a pulse ribbon onto points in spiral coords. */
|
tomwalters@0
|
244 /* Return the number of points in the plot window. */
|
tomwalters@0
|
245 npoints = map_spiral(frame,Xspiral,Yspiral,form_spl,zero_spl);
|
tomwalters@0
|
246
|
tomwalters@0
|
247 /* Plot spiral points and axis in window. */
|
tomwalters@0
|
248 if (dotsize_spl)
|
tomwalters@0
|
249 plotdots(state->window,Xspiral,Yspiral,Xdot,Ydot,npoints,dotsize_spl-1);
|
tomwalters@0
|
250 if (axis_spl)
|
tomwalters@0
|
251 Draw(state->window,Xaxis,Yaxis,naxis);
|
tomwalters@0
|
252
|
tomwalters@0
|
253 return ;
|
tomwalters@0
|
254 }
|
tomwalters@0
|
255
|
tomwalters@0
|
256
|
tomwalters@0
|
257
|
tomwalters@0
|
258 /****************************************************************************
|
tomwalters@0
|
259 Map an SAI frame onto a "pulse ribbon".
|
tomwalters@0
|
260
|
tomwalters@0
|
261 Convert a "frame" into a binary array where a `1' corresponds to a peak in
|
tomwalters@0
|
262 the SAI frame, and everwhere else is `0'. This binary array is called a
|
tomwalters@0
|
263 pulse ribbon.
|
tomwalters@0
|
264
|
tomwalters@0
|
265 Each SAI is a "frame". A frame is a matrix of "frameheight" rows by
|
tomwalters@0
|
266 "framewidth" columns. Each row corresponds to a frequency channel, and
|
tomwalters@0
|
267 frameheight corresponds to "chans" in image.c. The columns correspond to
|
tomwalters@0
|
268 the number of time samples in the "image_duration", and framewidth
|
tomwalters@0
|
269 corresponds to framewidth (or imagewidth/chans) in image.c.
|
tomwalters@0
|
270
|
tomwalters@0
|
271 The format of data in the input file, (short *frame), is "unmultiplexed".
|
tomwalters@0
|
272 This is an SAI frame in row-wise format, with the row corresponding
|
tomwalters@0
|
273 to the lowest-frequency channel comming first.
|
tomwalters@0
|
274
|
tomwalters@0
|
275 Every point in the sai frame is a coordinate pair:
|
tomwalters@0
|
276 (f,t); f=0,1,...,frameheight-1, t=0,1,...,framewidth-1.
|
tomwalters@0
|
277 (The lowest frequency channel has the lowest channel number f).
|
tomwalters@0
|
278 (The time-origin is the rightmost point, framewidth-1).
|
tomwalters@0
|
279
|
tomwalters@0
|
280 Peaks in the SAI frame are maxima along the time axis. Peaks are independent
|
tomwalters@0
|
281 of adjacent frequency channels.
|
tomwalters@0
|
282 A peak is defined as the highest point between zeroes, which also exceeds a
|
tomwalters@0
|
283 threshold. (A zero-crossing between peaks is guaranteed, since the cochleagram
|
tomwalters@0
|
284 signal has been half-wave rectified).
|
tomwalters@0
|
285
|
tomwalters@0
|
286 The number of peaks found is returned.
|
tomwalters@0
|
287 ****************************************************************************/
|
tomwalters@0
|
288 map_ribbon(frame,threshold)
|
tomwalters@0
|
289 short *frame;
|
tomwalters@0
|
290 int threshold;
|
tomwalters@0
|
291 {
|
tomwalters@0
|
292 short p, pmax;
|
tomwalters@0
|
293 int i, j, k, jk, npoints=0;
|
tomwalters@0
|
294
|
tomwalters@0
|
295 /* for each SAI row (each frequency channel) in turn */
|
tomwalters@0
|
296 for (i=0, k=0 ; i<frameheight ; i++, k+=framewidth+nwid) /* SSS */
|
tomwalters@0
|
297 /* for each time sample, working from right to left */
|
tomwalters@0
|
298 for (j=framewidth ; j>=0 ; j--) { /* SSS */
|
tomwalters@0
|
299 /* while zero, advance to next peak */
|
tomwalters@0
|
300 while (j>=(0-1) && frame[j+k]<=0) { /* SSS */
|
tomwalters@0
|
301 frame[j+k]=0;
|
tomwalters@0
|
302 j--;
|
tomwalters@0
|
303 }
|
tomwalters@0
|
304 /* while greater than zero, search for max peak */
|
tomwalters@0
|
305 for (pmax=0 ; j>=(0-1) && (p=frame[j+k])>0 ; j--) { /* SSS */
|
tomwalters@0
|
306 frame[j+k]=0;
|
tomwalters@0
|
307 if (p>pmax) {
|
tomwalters@0
|
308 pmax=p; jk=j+k;
|
tomwalters@0
|
309 }
|
tomwalters@0
|
310 }
|
tomwalters@0
|
311 /* record max peak if it exceeds the threshold */
|
tomwalters@0
|
312 if (pmax > threshold) {
|
tomwalters@0
|
313 frame[jk]=1;
|
tomwalters@0
|
314 npoints++;
|
tomwalters@0
|
315 }
|
tomwalters@0
|
316 }
|
tomwalters@0
|
317 return npoints;
|
tomwalters@0
|
318 }
|
tomwalters@0
|
319
|
tomwalters@0
|
320
|
tomwalters@0
|
321 /****************************************************************************
|
tomwalters@0
|
322 * Map 1's in pulse ribbon onto (x,y) spiral coords, and store in the
|
tomwalters@0
|
323 * given arrays if the points will appear in the plot window.
|
tomwalters@0
|
324 * Return the number of mapped points within the plot window.
|
tomwalters@0
|
325 ****************************************************************************/
|
tomwalters@0
|
326 map_spiral(frame,Xarray,Yarray,form_spl,zero_spl)
|
tomwalters@0
|
327 short *frame;
|
tomwalters@0
|
328 short *Xarray, *Yarray;
|
tomwalters@0
|
329 char form_spl;
|
tomwalters@0
|
330 float zero_spl;
|
tomwalters@0
|
331 {
|
tomwalters@0
|
332 float t, f, x, y;
|
tomwalters@0
|
333 float r0, r, theta;
|
tomwalters@0
|
334 int i, j, k, X, Y;
|
tomwalters@0
|
335 int points=0;
|
tomwalters@0
|
336
|
tomwalters@0
|
337 /* for each SAI row (each frequency channel) in turn */
|
tomwalters@0
|
338 for (i=0, k=0 ; i<frameheight ; i++, k+=framewidth+nwid) /* SSS */
|
tomwalters@0
|
339 /* for each time sample, working from right to left */
|
tomwalters@0
|
340 for (j=framewidth ; j>=0 ; j--) /* SSS */
|
tomwalters@0
|
341 if (frame[j+k] == 1) { /* for each `1' in pulse ribbon */
|
tomwalters@0
|
342 f = i;
|
tomwalters@0
|
343 t = (framewidth-1) - j ; /* time origin is on the right */
|
tomwalters@0
|
344
|
tomwalters@0
|
345 /* calculate polar coords of point, (r,theta): */
|
tomwalters@0
|
346 /* radius r at outer edge of spiral cycle, (ie at min f) */
|
tomwalters@0
|
347 /* radius r0, at same theta, at min f on previous cycle */
|
tomwalters@0
|
348 if (t > 1) theta = TWOPI * (log2(t) - zero_spl);
|
tomwalters@0
|
349 else theta = 0; /* special case of 1st cycle */
|
tomwalters@0
|
350 if (form_spl == 'A') { /* spiral == ARCHEMEDIAN */
|
tomwalters@0
|
351 r = theta;
|
tomwalters@0
|
352 if (r < 0) r = 0;
|
tomwalters@0
|
353 if (r > 0) r0 = r - TWOPI;
|
tomwalters@0
|
354 else r0 = 0; /* special case of 1st cycle */
|
tomwalters@0
|
355 }
|
tomwalters@0
|
356 if (form_spl == 'L') { /* spiral == LOGARITHMIC */
|
tomwalters@0
|
357 r = t;
|
tomwalters@0
|
358 if (t > 1) r0 = r/2;
|
tomwalters@0
|
359 else r0 = 0; /* special case of 1st cycle */
|
tomwalters@0
|
360 }
|
tomwalters@0
|
361 /* scale radius r for current frequency f (>= min f) */
|
tomwalters@0
|
362 /* scale such that spiral axis occupies its own channel */
|
tomwalters@0
|
363 r = r - ((f+1)/(frameheight+1)) * (r-r0);
|
tomwalters@0
|
364 /* convert polar to cartesian coords */
|
tomwalters@0
|
365 x = r*cos(theta);
|
tomwalters@0
|
366 y = r*sin(theta);
|
tomwalters@0
|
367 /* Transform into pixel coord system and store point */
|
tomwalters@0
|
368 X = px(x);
|
tomwalters@0
|
369 Y = py(y);
|
tomwalters@0
|
370 if (inbox(X,Y)) {
|
tomwalters@0
|
371 Xarray[points] = X;
|
tomwalters@0
|
372 Yarray[points++] = Y;
|
tomwalters@0
|
373 }
|
tomwalters@0
|
374 }
|
tomwalters@0
|
375
|
tomwalters@0
|
376 return points;
|
tomwalters@0
|
377 }
|
tomwalters@0
|
378
|
tomwalters@0
|
379
|
tomwalters@0
|
380 /****************************************************************************
|
tomwalters@0
|
381 * Generate points (X,Y coords) for spiral axis and store in given arrays.
|
tomwalters@0
|
382 * Return the number of points stored.
|
tomwalters@0
|
383 ****************************************************************************/
|
tomwalters@0
|
384 int gen_axis(Xarray,Yarray,naxis,form_spl,zero_spl)
|
tomwalters@0
|
385 short *Xarray, *Yarray;
|
tomwalters@0
|
386 int naxis;
|
tomwalters@0
|
387 char form_spl;
|
tomwalters@0
|
388 float zero_spl;
|
tomwalters@0
|
389 {
|
tomwalters@0
|
390 int t;
|
tomwalters@0
|
391 float r, theta;
|
tomwalters@0
|
392 int X, Y;
|
tomwalters@0
|
393 float x, y;
|
tomwalters@0
|
394 int points=0;
|
tomwalters@0
|
395
|
tomwalters@0
|
396 /* Calculate axis points in data coord system */
|
tomwalters@0
|
397 for (t=100 ; t < naxis ; t++) {
|
tomwalters@0
|
398 theta = TWOPI * (log2((float)t/100) - zero_spl);
|
tomwalters@0
|
399 if (theta < 0) theta = 0;
|
tomwalters@0
|
400 if (form_spl == 'A') /* spiral == Achemedian */
|
tomwalters@0
|
401 r = theta;
|
tomwalters@0
|
402 else /* spiral == Logarithmic */
|
tomwalters@0
|
403 r = (float)t/100;
|
tomwalters@0
|
404 x = r*cos(theta);
|
tomwalters@0
|
405 y = r*sin(theta);
|
tomwalters@0
|
406 /* Transform into pixel coord system and store */
|
tomwalters@0
|
407 X = px(x);
|
tomwalters@0
|
408 Y = py(y);
|
tomwalters@0
|
409 if (inbox(X,Y)) {
|
tomwalters@0
|
410 Xarray[points] = X;
|
tomwalters@0
|
411 Yarray[points++] = Y;
|
tomwalters@0
|
412 }
|
tomwalters@0
|
413
|
tomwalters@0
|
414 }
|
tomwalters@0
|
415 return points;
|
tomwalters@0
|
416 }
|
tomwalters@0
|
417
|
tomwalters@0
|
418
|
tomwalters@0
|
419
|
tomwalters@0
|
420 /****************************************************************************
|
tomwalters@0
|
421 * Plot dots of size d.
|
tomwalters@0
|
422 *
|
tomwalters@0
|
423 * Plotting in a given window uses the glib routines Draw and Plot.
|
tomwalters@0
|
424 * These routines, and associated structures, are declared in windows.h.
|
tomwalters@0
|
425 * The WindowObject structure has an "entries" pointer to a WindowEntries
|
tomwalters@0
|
426 * structure, and this holds pointers to a set of functions which operate on
|
tomwalters@0
|
427 * the window. The window functions, and the routine newDisplayWindow which
|
tomwalters@0
|
428 * allocates a new WindowObject, are defined in X.c.
|
tomwalters@0
|
429 *
|
tomwalters@0
|
430 * void Draw(win,X,Y,points)
|
tomwalters@0
|
431 * Takes two arrays of shorts, one with x-coords the other with y-coords.
|
tomwalters@0
|
432 * The number of x's = the number of y's = "points".
|
tomwalters@0
|
433 * The user must ensure that the data coords are scaled into the pixel
|
tomwalters@0
|
434 * coord system. This is as follows: (1,1) is bottom-left corner, and
|
tomwalters@0
|
435 * (width,height) is top-right corner.
|
tomwalters@0
|
436 * void Plot(win,X,Y,points)
|
tomwalters@0
|
437 * Same as Draw, but plots points.
|
tomwalters@0
|
438 ****************************************************************************/
|
tomwalters@0
|
439 plotdots(win,Xspiral,Yspiral,X,Y,npoints,d)
|
tomwalters@0
|
440 WindowObject win;
|
tomwalters@0
|
441 short *Xspiral, *Yspiral;
|
tomwalters@0
|
442 short *X, *Y;
|
tomwalters@0
|
443 int npoints, d;
|
tomwalters@0
|
444 {
|
tomwalters@0
|
445 int x, y, i;
|
tomwalters@0
|
446
|
tomwalters@0
|
447 if (d==0) /* dotsize = 1 */
|
tomwalters@0
|
448 Plot(win,Xspiral,Yspiral,npoints);
|
tomwalters@0
|
449 else { /* dotsize > 1 */
|
tomwalters@0
|
450 for (x=(-d) ; x<=d ; x++)
|
tomwalters@0
|
451 for (y=(-d) ; y<=d ; y++) {
|
tomwalters@0
|
452 for (i=0 ; i<npoints ; i++) {
|
tomwalters@0
|
453 X[i] = Xspiral[i] + x;
|
tomwalters@0
|
454 Y[i] = Yspiral[i] + y;
|
tomwalters@0
|
455 }
|
tomwalters@0
|
456 Plot(win,X,Y,npoints);
|
tomwalters@0
|
457 }
|
tomwalters@0
|
458 }
|
tomwalters@0
|
459 }
|
tomwalters@0
|
460
|