tioga 1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/Tioga_README +372 -0
  2. data/lgpl.txt +504 -0
  3. data/split/Dtable/defs.h +33 -0
  4. data/split/Dtable/dtable.c +1928 -0
  5. data/split/Dtable/dtable_intern.h +144 -0
  6. data/split/Dtable/dvector.h +61 -0
  7. data/split/Dtable/extconf.rb +4 -0
  8. data/split/Dtable/include/dtable.h +35 -0
  9. data/split/Dtable/lib/Dtable_extras.rb +90 -0
  10. data/split/Dtable/namespace.h +47 -0
  11. data/split/Dtable/safe_double.h +104 -0
  12. data/split/Dtable/symbols.c +92 -0
  13. data/split/Dtable/symbols.h +52 -0
  14. data/split/Dvector/defs.h +33 -0
  15. data/split/Dvector/dvector.c +5486 -0
  16. data/split/Dvector/dvector_intern.h +142 -0
  17. data/split/Dvector/extconf.rb +4 -0
  18. data/split/Dvector/include/dvector.h +61 -0
  19. data/split/Dvector/lib/Dvector_extras.rb +328 -0
  20. data/split/Dvector/lib/Numeric_extras.rb +134 -0
  21. data/split/Dvector/namespace.h +47 -0
  22. data/split/Dvector/safe_double.h +104 -0
  23. data/split/Dvector/symbols.c +92 -0
  24. data/split/Dvector/symbols.h +52 -0
  25. data/split/Flate/defs.h +33 -0
  26. data/split/Flate/extconf.rb +19 -0
  27. data/split/Flate/flate.c +156 -0
  28. data/split/Flate/flate_intern.h +97 -0
  29. data/split/Flate/include/flate.h +98 -0
  30. data/split/Flate/namespace.h +47 -0
  31. data/split/Flate/safe_double.h +104 -0
  32. data/split/Flate/symbols.c +92 -0
  33. data/split/Flate/symbols.h +52 -0
  34. data/split/Function/defs.h +33 -0
  35. data/split/Function/dvector.h +61 -0
  36. data/split/Function/extconf.rb +4 -0
  37. data/split/Function/function.c +988 -0
  38. data/split/Function/joint_qsort.c +258 -0
  39. data/split/Function/lib/Function_extras.rb +44 -0
  40. data/split/Function/namespace.h +47 -0
  41. data/split/Function/safe_double.h +104 -0
  42. data/split/Function/symbols.c +92 -0
  43. data/split/Function/symbols.h +52 -0
  44. data/split/Tioga/axes.c +774 -0
  45. data/split/Tioga/defs.h +33 -0
  46. data/split/Tioga/dtable.h +35 -0
  47. data/split/Tioga/dvector.h +61 -0
  48. data/split/Tioga/extconf.rb +4 -0
  49. data/split/Tioga/figures.c +672 -0
  50. data/split/Tioga/figures.h +855 -0
  51. data/split/Tioga/flate.h +98 -0
  52. data/split/Tioga/init.c +524 -0
  53. data/split/Tioga/lib/Arcs_and_Circles.rb +64 -0
  54. data/split/Tioga/lib/ColorConstants.rb +274 -0
  55. data/split/Tioga/lib/Colorbars.rb +10 -0
  56. data/split/Tioga/lib/Colormaps.rb +105 -0
  57. data/split/Tioga/lib/Coordinate_Conversions.rb +194 -0
  58. data/split/Tioga/lib/Creating_Paths.rb +94 -0
  59. data/split/Tioga/lib/Doc.rb +91 -0
  60. data/split/Tioga/lib/Executive.rb +515 -0
  61. data/split/Tioga/lib/FigMkr.rb +2224 -0
  62. data/split/Tioga/lib/FigureConstants.rb +125 -0
  63. data/split/Tioga/lib/Figures_and_Plots.rb +268 -0
  64. data/split/Tioga/lib/Images.rb +278 -0
  65. data/split/Tioga/lib/Legends.rb +190 -0
  66. data/split/Tioga/lib/MarkerConstants.rb +122 -0
  67. data/split/Tioga/lib/Markers.rb +129 -0
  68. data/split/Tioga/lib/Page_Frame_Bounds.rb +567 -0
  69. data/split/Tioga/lib/Rectangles.rb +94 -0
  70. data/split/Tioga/lib/Shading.rb +100 -0
  71. data/split/Tioga/lib/Special_Paths.rb +307 -0
  72. data/split/Tioga/lib/Strokes.rb +129 -0
  73. data/split/Tioga/lib/TeX_Text.rb +454 -0
  74. data/split/Tioga/lib/TexPreamble.rb +358 -0
  75. data/split/Tioga/lib/Titles_and_Labels.rb +306 -0
  76. data/split/Tioga/lib/Transparency.rb +89 -0
  77. data/split/Tioga/lib/Using_Paths.rb +164 -0
  78. data/split/Tioga/lib/Utils.rb +74 -0
  79. data/split/Tioga/lib/X_and_Y_Axes.rb +749 -0
  80. data/split/Tioga/lib/irb_tioga.rb +122 -0
  81. data/split/Tioga/lib/tioga.rb +1 -0
  82. data/split/Tioga/lib/tioga_ui.rb +5 -0
  83. data/split/Tioga/lib/tioga_ui_cmds.rb +793 -0
  84. data/split/Tioga/makers.c +989 -0
  85. data/split/Tioga/mk_tioga_sty.rb +53 -0
  86. data/split/Tioga/namespace.h +47 -0
  87. data/split/Tioga/pdf_font_dicts.c +18253 -0
  88. data/split/Tioga/pdfcolor.c +486 -0
  89. data/split/Tioga/pdfcoords.c +505 -0
  90. data/split/Tioga/pdffile.c +342 -0
  91. data/split/Tioga/pdfimage.c +536 -0
  92. data/split/Tioga/pdfpath.c +914 -0
  93. data/split/Tioga/pdfs.h +229 -0
  94. data/split/Tioga/pdftext.c +443 -0
  95. data/split/Tioga/safe_double.h +104 -0
  96. data/split/Tioga/symbols.c +92 -0
  97. data/split/Tioga/symbols.h +52 -0
  98. data/split/Tioga/texout.c +380 -0
  99. data/split/defs.h +33 -0
  100. data/split/extconf.rb +107 -0
  101. data/split/mkmf2.rb +1612 -0
  102. data/split/namespace.h +47 -0
  103. data/split/safe_double.h +104 -0
  104. data/split/scripts/tioga +4 -0
  105. data/split/symbols.c +92 -0
  106. data/split/symbols.h +52 -0
  107. data/tests/dtable_test.data +6 -0
  108. data/tests/dvector_read_test.data +1 -0
  109. data/tests/dvector_test.data +101 -0
  110. data/tests/tc_Dtable.rb +221 -0
  111. data/tests/tc_Dvector.rb +791 -0
  112. data/tests/tc_FMkr.rb +162 -0
  113. data/tests/tc_Flate.rb +45 -0
  114. data/tests/tc_Function.rb +111 -0
  115. data/tests/ts_Tioga.rb +38 -0
  116. metadata +163 -0
@@ -0,0 +1,989 @@
1
+ /* makers.c */
2
+ /*
3
+ Copyright (C) 2005 Bill Paxton
4
+
5
+ This file is part of Tioga.
6
+
7
+ Tioga is free software; you can redistribute it and/or modify
8
+ it under the terms of the GNU General Library Public License as published
9
+ by the Free Software Foundation; either version 2 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Tioga is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Library General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Library General Public License
18
+ along with Tioga; if not, write to the Free Software
19
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+ #include "figures.h"
23
+
24
+
25
+ /* Lines */
26
+
27
+ void c_private_make_spline_interpolated_points(FM *p, VALUE Xvec, VALUE Yvec, VALUE Xvec_data, VALUE Yvec_data,
28
+ int start_clamped, double start_slope, int end_clamped, double end_slope) {
29
+ int i, n_pts_data;
30
+ double *As, *Bs, *Cs, *Ds;
31
+ long xlen, ylen, xdlen, ydlen;
32
+ double *Xs = Dvector_Data_for_Write(Xvec, &xlen);
33
+ double *Ys = Dvector_Data_for_Write(Yvec, &ylen);
34
+ double *X_data = Dvector_Data_for_Read(Xvec_data, &xdlen);
35
+ double *Y_data = Dvector_Data_for_Read(Yvec_data, &ydlen);
36
+ if (Xs == NULL || Ys == NULL || X_data == NULL || Y_data == NULL || xdlen != ydlen) {
37
+ rb_raise(rb_eArgError, "Sorry: bad args for make_curves");
38
+ }
39
+ if (xlen == 0) return;
40
+ n_pts_data = xdlen;
41
+ As = Y_data;
42
+ Bs = (double *)ALLOC_N(double, n_pts_data);
43
+ Cs = (double *)ALLOC_N(double, n_pts_data);
44
+ Ds = (double *)ALLOC_N(double, n_pts_data);
45
+ c_dvector_create_spline_interpolant(n_pts_data, X_data, Y_data,
46
+ start_clamped, start_slope, end_clamped, end_slope, Bs, Cs, Ds);
47
+ Ys = Dvector_Data_Resize(Yvec, xlen);
48
+ for (i = 0; i < xlen; i++)
49
+ Ys[i] = c_dvector_spline_interpolate(Xs[i], n_pts_data, X_data, As, Bs, Cs, Ds);
50
+ free(Ds); free(Cs); free(Bs);
51
+ USE_P
52
+ }
53
+
54
+ VALUE FM_private_make_spline_interpolated_points(VALUE fmkr, VALUE Xvec, VALUE Yvec, VALUE Xvec_data, VALUE Yvec_data,
55
+ VALUE start_slope, VALUE end_slope) {
56
+ FM *p = Get_FM(fmkr);
57
+ bool start_clamped = (start_slope != Qnil), end_clamped = (end_slope != Qnil);
58
+ double start=0, end=0;
59
+ if (start_clamped) {
60
+ start_slope = rb_Float(start_slope);
61
+ start = NUM2DBL(start_slope);
62
+ }
63
+ if (end_clamped) {
64
+ end_slope = rb_Float(end_slope);
65
+ end = NUM2DBL(end_slope);
66
+ }
67
+ c_private_make_spline_interpolated_points(p, Xvec, Yvec, Xvec_data, Yvec_data,
68
+ start_clamped, start, end_clamped, end);
69
+ return fmkr;
70
+ }
71
+
72
+ void c_make_steps(FM *p, VALUE Xvec, VALUE Yvec, VALUE Xvec_data, VALUE Yvec_data,
73
+ double xfirst, double yfirst, double xlast, double ylast){
74
+ double xnext, xprev, x;
75
+ int n_pts_to_add;
76
+ int i, j, n, old_length, new_length;
77
+ long xlen, ylen, xdlen, ydlen;
78
+ double *Xs = Dvector_Data_for_Write(Xvec, &xlen);
79
+ double *Ys = Dvector_Data_for_Write(Yvec, &ylen);
80
+ double *X_data = Dvector_Data_for_Read(Xvec_data, &xdlen);
81
+ double *Y_data = Dvector_Data_for_Read(Yvec_data, &ydlen);
82
+ if (Xs == NULL || Ys == NULL || X_data == NULL || Y_data == NULL
83
+ || xdlen != ydlen || xlen != ylen) {
84
+ rb_raise(rb_eArgError, "Sorry: bad args for make_steps");
85
+ }
86
+ n = xdlen;
87
+ n_pts_to_add = 2*(n+1);
88
+ old_length = xlen;
89
+ new_length = old_length + n_pts_to_add;
90
+ Xs = Dvector_Data_Resize(Xvec, new_length);
91
+ Ys = Dvector_Data_Resize(Yvec, new_length);
92
+ for (i = 0, j = 0; i <= n; i++, j += 2) {
93
+ xprev = (i==0)? xfirst : X_data[i-1];
94
+ xnext = (i==n)? xlast : X_data[i];
95
+ x = 0.5*(xprev + xnext);
96
+ Xs[j+old_length] = Xs[j+1+old_length] = x;
97
+ }
98
+ Ys[0] = yfirst;
99
+ for (i = 0, j = 1; i < n; i++, j += 2) {
100
+ Ys[j+old_length] = Ys[j+1+old_length] = Y_data[i];
101
+ }
102
+ Ys[n_pts_to_add-1+old_length] = ylast;
103
+ USE_P
104
+ }
105
+
106
+ VALUE FM_private_make_steps(VALUE fmkr, VALUE Xvec, VALUE Yvec, VALUE Xvec_data, VALUE Yvec_data,
107
+ VALUE xfirst, VALUE yfirst, VALUE xlast, VALUE ylast) {
108
+ FM *p = Get_FM(fmkr);
109
+ xfirst = rb_Float(xfirst);
110
+ yfirst = rb_Float(yfirst);
111
+ xlast = rb_Float(xlast);
112
+ ylast = rb_Float(ylast);
113
+ c_make_steps(p, Xvec, Yvec, Xvec_data, Yvec_data,
114
+ NUM2DBL(xfirst), NUM2DBL(yfirst), NUM2DBL(xlast), NUM2DBL(ylast));
115
+ return fmkr;
116
+ }
117
+
118
+ /*
119
+ CONREC: A Contouring Subroutine
120
+ written by Paul Bourke
121
+ see: http://astronomy.swin.edu.au/~pbourke/projection/conrec/
122
+
123
+ Copyright (c) 1996-1997 Nicholas Yue
124
+
125
+ This software is copyrighted by Nicholas Yue. This code is base on the work of
126
+ Paul D. Bourke CONREC.F routine
127
+
128
+ The authors hereby grant permission to use, copy, and distribute this
129
+ software and its documentation for any purpose, provided that existing
130
+ copyright notices are retained in all copies and that this notice is included
131
+ verbatim in any distributions. Additionally, the authors grant permission to
132
+ modify this software and its documentation for any purpose, provided that
133
+ such modifications are not distributed without the explicit consent of the
134
+ authors and that existing copyright notices are retained in all copies. Some
135
+ of the algorithms implemented by this software are patented, observe all
136
+ applicable patent law.
137
+
138
+ IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
139
+ DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
140
+ OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
141
+ EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
142
+
143
+ THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
144
+ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
145
+ PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN
146
+ "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
147
+ MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
148
+ */
149
+
150
+ //=============================================================================
151
+ //
152
+ // CONREC is a contouring subroutine for rectangularily spaced data.
153
+ //
154
+ // It emits calls to a line drawing subroutine supplied by the user
155
+ // which draws a contour map corresponding to real*4data on a randomly
156
+ // spaced rectangular grid. The coordinates emitted are in the same
157
+ // units given in the x() and y() arrays.
158
+ //
159
+ // Any number of contour levels may be specified but they must be
160
+ // in order of increasing value.
161
+ //
162
+ // As this code is ported from FORTRAN-77, please be very careful of the
163
+ // various indices like ilb,iub,jlb and jub, remeber that C/C++ indices
164
+ // starts from zero (0)
165
+ //
166
+ //=============================================================================
167
+ #include <stdio.h>
168
+ #include <math.h>
169
+
170
+ #define xsect(p1,p2) (h[p2]*xh[p1]-h[p1]*xh[p2])/(h[p2]-h[p1])
171
+ #define ysect(p1,p2) (h[p2]*yh[p1]-h[p1]*yh[p2])/(h[p2]-h[p1])
172
+ #define min(x,y) (x<y?x:y)
173
+ #define max(x,y) (x>y?x:y)
174
+
175
+ #define PUSH_POINT(x,y,j) { \
176
+ Dvector_Store_Double(dest_xs, j, x); \
177
+ Dvector_Store_Double(dest_ys, j, y); \
178
+ j++; }
179
+
180
+ int conrec(double **d,
181
+ int ilb,
182
+ int iub,
183
+ int jlb,
184
+ int jub,
185
+ double *x,
186
+ double *y,
187
+ int nc,
188
+ double *z,
189
+ VALUE dest_xs,
190
+ VALUE dest_ys,
191
+ VALUE gaps,
192
+ double x_limit,
193
+ double y_limit)
194
+ // d ! matrix of data to contour
195
+ // ilb,iub,jlb,jub ! index bounds of data matrix
196
+ // x ! data matrix column coordinates
197
+ // y ! data matrix row coordinates
198
+ // nc ! number of contour levels
199
+ // z ! contour levels in increasing order
200
+ {
201
+ int num_pts = 0;
202
+ double x_prev=0.0, y_prev=0.0;
203
+ int m1,m2,m3,case_value;
204
+ double dmin,dmax,x1=0.0,x2=0.0,y1=0.0,y2=0.0;
205
+ register int i,j,k,m;
206
+ double h[5];
207
+ int sh[5];
208
+ double xh[5],yh[5];
209
+ //===========================================================================
210
+ // The indexing of im and jm should be noted as it has to start from zero
211
+ // unlike the fortran counter part
212
+ //===========================================================================
213
+ int im[4] = {0,1,1,0},jm[4]={0,0,1,1};
214
+ //===========================================================================
215
+ // Note that castab is arranged differently from the FORTRAN code because
216
+ // Fortran and C/C++ arrays are transposes of each other, in this case
217
+ // it is more tricky as castab is in 3 dimension
218
+ //===========================================================================
219
+ int castab[3][3][3] =
220
+ {
221
+ {
222
+ {0,0,8},{0,2,5},{7,6,9}
223
+ },
224
+ {
225
+ {0,3,4},{1,3,1},{4,3,0}
226
+ },
227
+ {
228
+ {9,6,7},{5,2,0},{8,0,0}
229
+ }
230
+ };
231
+ for (j=(jub-1);j>=jlb;j--) {
232
+ for (i=ilb;i<=iub-1;i++) {
233
+ double temp1,temp2;
234
+ temp1 = min(d[i][j],d[i][j+1]);
235
+ temp2 = min(d[i+1][j],d[i+1][j+1]);
236
+ dmin = min(temp1,temp2);
237
+ temp1 = max(d[i][j],d[i][j+1]);
238
+ temp2 = max(d[i+1][j],d[i+1][j+1]);
239
+ dmax = max(temp1,temp2);
240
+ if (dmax>=z[0]&&dmin<=z[nc-1]) {
241
+ for (k=0;k<nc;k++) {
242
+ if (z[k]>=dmin&&z[k]<=dmax) {
243
+ for (m=4;m>=0;m--) {
244
+ if (m>0) {
245
+ //=============================================================
246
+ // The indexing of im and jm should be noted as it has to
247
+ // start from zero
248
+ //=============================================================
249
+ h[m] = d[i+im[m-1]][j+jm[m-1]]-z[k];
250
+ xh[m] = x[i+im[m-1]];
251
+ yh[m] = y[j+jm[m-1]];
252
+ } else {
253
+ h[0] = 0.25*(h[1]+h[2]+h[3]+h[4]);
254
+ xh[0]=0.5*(x[i]+x[i+1]);
255
+ yh[0]=0.5*(y[j]+y[j+1]);
256
+ }
257
+ if (h[m]>0.0) {
258
+ sh[m] = 1;
259
+ } else if (h[m]<0.0) {
260
+ sh[m] = -1;
261
+ } else
262
+ sh[m] = 0;
263
+ }
264
+ //=================================================================
265
+ //
266
+ // Note: at this stage the relative heights of the corners and the
267
+ // centre are in the h array, and the corresponding coordinates are
268
+ // in the xh and yh arrays. The centre of the box is indexed by 0
269
+ // and the 4 corners by 1 to 4 as shown below.
270
+ // Each triangle is then indexed by the parameter m, and the 3
271
+ // vertices of each triangle are indexed by parameters m1,m2,and
272
+ // m3.
273
+ // It is assumed that the centre of the box is always vertex 2
274
+ // though this isimportant only when all 3 vertices lie exactly on
275
+ // the same contour level, in which case only the side of the box
276
+ // is drawn.
277
+ //
278
+ //
279
+ // vertex 4 +-------------------+ vertex 3
280
+ // | \ / |
281
+ // | \ m-3 / |
282
+ // | \ / |
283
+ // | \ / |
284
+ // | m=2 X m=2 | the centre is vertex 0
285
+ // | / \ |
286
+ // | / \ |
287
+ // | / m=1 \ |
288
+ // | / \ |
289
+ // vertex 1 +-------------------+ vertex 2
290
+ //
291
+ //
292
+ //
293
+ // Scan each triangle in the box
294
+ //
295
+ //=================================================================
296
+ for (m=1;m<=4;m++) {
297
+ m1 = m;
298
+ m2 = 0;
299
+ if (m!=4)
300
+ m3 = m+1;
301
+ else
302
+ m3 = 1;
303
+ case_value = castab[sh[m1]+1][sh[m2]+1][sh[m3]+1];
304
+ if (case_value!=0) {
305
+ switch (case_value) {
306
+ //===========================================================
307
+ // Case 1 - Line between vertices 1 and 2
308
+ //===========================================================
309
+ case 1:
310
+ x1=xh[m1];
311
+ y1=yh[m1];
312
+ x2=xh[m2];
313
+ y2=yh[m2];
314
+ break;
315
+ //===========================================================
316
+ // Case 2 - Line between vertices 2 and 3
317
+ //===========================================================
318
+ case 2:
319
+ x1=xh[m2];
320
+ y1=yh[m2];
321
+ x2=xh[m3];
322
+ y2=yh[m3];
323
+ break;
324
+ //===========================================================
325
+ // Case 3 - Line between vertices 3 and 1
326
+ //===========================================================
327
+ case 3:
328
+ x1=xh[m3];
329
+ y1=yh[m3];
330
+ x2=xh[m1];
331
+ y2=yh[m1];
332
+ break;
333
+ //===========================================================
334
+ // Case 4 - Line between vertex 1 and side 2-3
335
+ //===========================================================
336
+ case 4:
337
+ x1=xh[m1];
338
+ y1=yh[m1];
339
+ x2=xsect(m2,m3);
340
+ y2=ysect(m2,m3);
341
+ break;
342
+ //===========================================================
343
+ // Case 5 - Line between vertex 2 and side 3-1
344
+ //===========================================================
345
+ case 5:
346
+ x1=xh[m2];
347
+ y1=yh[m2];
348
+ x2=xsect(m3,m1);
349
+ y2=ysect(m3,m1);
350
+ break;
351
+ //===========================================================
352
+ // Case 6 - Line between vertex 3 and side 1-2
353
+ //===========================================================
354
+ case 6:
355
+ x1=xh[m3];
356
+ y1=yh[m3];
357
+ x2=xsect(m1,m2);
358
+ y2=ysect(m1,m2);
359
+ break;
360
+ //===========================================================
361
+ // Case 7 - Line between sides 1-2 and 2-3
362
+ //===========================================================
363
+ case 7:
364
+ x1=xsect(m1,m2);
365
+ y1=ysect(m1,m2);
366
+ x2=xsect(m2,m3);
367
+ y2=ysect(m2,m3);
368
+ break;
369
+ //===========================================================
370
+ // Case 8 - Line between sides 2-3 and 3-1
371
+ //===========================================================
372
+ case 8:
373
+ x1=xsect(m2,m3);
374
+ y1=ysect(m2,m3);
375
+ x2=xsect(m3,m1);
376
+ y2=ysect(m3,m1);
377
+ break;
378
+ //===========================================================
379
+ // Case 9 - Line between sides 3-1 and 1-2
380
+ //===========================================================
381
+ case 9:
382
+ x1=xsect(m3,m1);
383
+ y1=ysect(m3,m1);
384
+ x2=xsect(m1,m2);
385
+ y2=ysect(m1,m2);
386
+ break;
387
+ default:
388
+ break;
389
+ }
390
+ double dx = x1 - x_prev, dy = y1 - y_prev;
391
+ if (dx < 0) dx = -dx; if (dy < 0) dy = -dy;
392
+ if (num_pts == 0 || dx > x_limit || dy > y_limit) {
393
+ if (num_pts > 0) rb_ary_push(gaps, INT2FIX(num_pts));
394
+ PUSH_POINT(x1,y1,num_pts);
395
+ }
396
+ PUSH_POINT(x2,y2,num_pts);
397
+ x_prev = x2; y_prev = y2;
398
+ }
399
+ }
400
+ }
401
+ }
402
+ }
403
+ }
404
+ }
405
+ return 0;
406
+ }
407
+
408
+ /* end of conrec */
409
+
410
+
411
+
412
+
413
+
414
+
415
+
416
+
417
+ // the following code is from Gri
418
+
419
+
420
+
421
+
422
+ #include <math.h>
423
+ #include <stdio.h>
424
+ #include <string.h>
425
+
426
+ // globals to this file
427
+ static int nx_1, ny_1, iGT, jGT, iLE, jLE;
428
+
429
+ static void free_space_for_curve();
430
+ static void get_space_for_curve();
431
+ static void draw_the_contour(
432
+ VALUE dest_xs,
433
+ VALUE dest_ys,
434
+ VALUE gaps);
435
+
436
+ static bool trace_contour(double z0,
437
+ double *x,
438
+ double *y,
439
+ double **z,
440
+ double **legit,
441
+ VALUE dest_xs,
442
+ VALUE dest_ys,
443
+ VALUE gaps);
444
+
445
+ static int FLAG(int ni, int nj, int ind);
446
+ static int append_segment(double xr, double yr, double zr, double OKr,
447
+ double xs, double ys, double zs, double OKs,
448
+ double z0);
449
+
450
+ // Space for curve, shared by several routines
451
+ static double *xcurve, *ycurve;
452
+ static bool *legitcurve;
453
+ #define INITIAL_CURVE_SIZE 100
454
+ static int num_in_curve, max_in_curve, num_in_path;
455
+ static bool curve_storage_exists = false;
456
+
457
+
458
+ static void
459
+ free_space_for_curve()
460
+ {
461
+ if (curve_storage_exists) {
462
+ free(xcurve);
463
+ free(ycurve);
464
+ free(legitcurve);
465
+ curve_storage_exists = false;
466
+ }
467
+ num_in_curve = 0;
468
+ num_in_path = 0;
469
+ }
470
+
471
+ static void
472
+ get_space_for_curve()
473
+ {
474
+ max_in_curve = INITIAL_CURVE_SIZE;
475
+ if(curve_storage_exists) {
476
+ rb_raise(rb_eArgError, "storage is messed up (internal error)");
477
+ return; // will not execute
478
+ }
479
+ xcurve = ALLOC_N(double, max_in_curve);
480
+ ycurve = ALLOC_N(double, max_in_curve);
481
+ legitcurve = ALLOC_N(bool, max_in_curve);
482
+ curve_storage_exists = true;
483
+ num_in_curve = 0;
484
+ num_in_path = 0;
485
+ }
486
+
487
+
488
+
489
+ // gr_contour() -- draw contour line for gridded data
490
+ //
491
+ // DESCRIPTION: Draws a contour for the value z0, through data z[i][j] defined
492
+ // on the rectangular grid x[i] and y[j] (where 0<=i<nx and 0<=j<ny). That
493
+ // the grid is rectangular but needn't be square or regular. Contours are
494
+ // drawn only in triangular regions surrounded by 3 good points (ie, 3 points
495
+ // with legit[i][j] != 0.0).
496
+ //
497
+ // The contour is labelled, with the string// lab, at intervals of
498
+ // contour_space_later centimeters, starting with a space of
499
+ // contour_space_first from the beginning of the trace.
500
+ //
501
+ // CONTOUR_VALUE MISSING_VALUE
502
+ static void
503
+ gr_contour(
504
+ double *x,
505
+ double *y,
506
+ double **z,
507
+ double **legit,
508
+ int nx,
509
+ int ny,
510
+ double z0,
511
+ VALUE dest_xs,
512
+ VALUE dest_ys,
513
+ VALUE gaps)
514
+ {
515
+ register int i, j;
516
+ // Test for errors
517
+ if (nx <= 0) rb_raise(rb_eArgError, "nx<=0 (internal error)");
518
+ if (ny <= 0) rb_raise(rb_eArgError, "ny<=0 (internal error)");
519
+ // Save some globals
520
+ nx_1 = nx - 1;
521
+ ny_1 = ny - 1;
522
+ // Clear all switches.
523
+ FLAG(nx, ny, -1);
524
+ // Get space for the curve.
525
+ get_space_for_curve();
526
+
527
+ // Search for a contour intersecting various places on the grid. Whenever
528
+ // a contour is found to be between two grid points, call trace_contour()
529
+ // after defining the global variables iLE,jLE,iGT,jGT so that
530
+ // z[iLE]jLE] <= z0 < z[iGT][jGT], where legit[iLE][jLE] != 0
531
+ // and legit[iGT][jGT] != 0.
532
+ //
533
+ // NOTE: always start a contour running upwards (to greater j), between
534
+ // two sideways neighboring points (same j). Later, in trace_contour(),
535
+ // test 'locate' for value 5. If it's 5, it means that the same geometry
536
+ // obtains, so set a flag and check whether already set. If already
537
+ // set, it means we've traced this contour before, so trace_contour()
538
+ // knows to stop then.
539
+
540
+ // Search bottom
541
+ for (i = 1; i < nx; i++) {
542
+ j = 0;
543
+ while (j < ny_1) {
544
+ // move north to first legit point
545
+ while (j < ny_1
546
+ && (legit == NULL || !(legit[i][j] != 0.0 && legit[i - 1][j] != 0.0))
547
+ ) {
548
+ j++;
549
+ }
550
+ // trace a contour if it hits here
551
+ if (j < ny_1 && z[i][j] > z0 && z[i - 1][j] <= z0) {
552
+ iLE = i - 1;
553
+ jLE = j;
554
+ iGT = i;
555
+ jGT = j;
556
+ trace_contour(z0, x, y, z, legit, dest_xs, dest_ys, gaps);
557
+ }
558
+ // Space through legit points, that is, skipping through good
559
+ // data looking for another island of bad data which will
560
+ // thus be a new 'bottom edge'.
561
+ while (j < ny_1 && (legit == NULL || (legit[i][j] != 0.0 && legit[i - 1][j] != 0.0)))
562
+ j++;
563
+ }
564
+ }
565
+
566
+ // search right edge
567
+ for (j = 1; j < ny; j++) {
568
+ i = nx_1;
569
+ while (i > 0) {
570
+ // move west to first legit point
571
+ while (i > 0 && (legit == NULL || !(legit[i][j] != 0.0 && legit[i][ j - 1] != 0.0)))
572
+ i--;
573
+ // trace a contour if it hits here
574
+ if (i > 0 && z[i][j] > z0 && z[i][j - 1] <= z0) {
575
+ iLE = i;
576
+ jLE = j - 1;
577
+ iGT = i;
578
+ jGT = j;
579
+ trace_contour(z0, x, y, z, legit, dest_xs, dest_ys, gaps);
580
+ }
581
+ // space through legit points
582
+ while (i > 0 && (legit == NULL || legit[i][j] != 0.0 && legit[i][ j - 1] != 0.0))
583
+ i--;
584
+ }
585
+ }
586
+
587
+ // search top edge
588
+ for (i = nx_1 - 1; i > -1; i--) {
589
+ j = ny_1;
590
+ while (j > 0) {
591
+ while (j > 0 && (legit == NULL || !(legit[i][j] != 0.0 && legit[i + 1][ j] != 0.0)))
592
+ j--;
593
+ // trace a contour if it hits here
594
+ if (j > 0 && z[i][j] > z0 && z[i + 1][ j] <= z0) {
595
+ iLE = i + 1;
596
+ jLE = j;
597
+ iGT = i;
598
+ jGT = j;
599
+ trace_contour(z0, x, y, z, legit, dest_xs, dest_ys, gaps);
600
+ }
601
+ // space through legit points
602
+ while (j > 0 && (legit == NULL || legit[i][j] != 0.0 && legit[i + 1][ j] != 0.0))
603
+ j--;
604
+ }
605
+ }
606
+
607
+ // search left edge
608
+ for (j = ny_1 - 1; j > -1; j--) {
609
+ i = 0;
610
+ while (i < nx_1) {
611
+ while (i < nx_1 && (legit == NULL || !(legit[i][j] != 0.0 && legit[i][ j + 1] != 0.0)))
612
+ i++;
613
+ // trace a contour if it hits here
614
+ if (i < nx_1 && z[i][j] > z0 && z[i][j + 1] <= z0) {
615
+ iLE = i;
616
+ jLE = j + 1;
617
+ iGT = i;
618
+ jGT = j;
619
+ trace_contour(z0, x, y, z, legit, dest_xs, dest_ys, gaps);
620
+ }
621
+ // space through legit points
622
+ while (i < nx_1 && (legit == NULL || legit[i][j] != 0.0 && legit[i][ j + 1] != 0.0))
623
+ i++;
624
+ }
625
+ }
626
+
627
+ // Search interior. Pass up from bottom (starting at left), through all
628
+ // interior points. Look for contours which enter, with high to right,
629
+ // between iLE on left and iGT on right.
630
+ for (j = 1; j < ny_1; j++) {
631
+ int flag_is_set;
632
+ for (i = 1; i < nx; i++) {
633
+ // trace a contour if it hits here
634
+ flag_is_set = FLAG(i, j, 0);
635
+ if (flag_is_set < 0)
636
+ rb_raise(rb_eArgError, "ran out of storage (internal error)");
637
+ if (!flag_is_set
638
+ && (legit == NULL || legit[i][j] != 0.0)
639
+ && z[i][j] > z0
640
+ && (legit == NULL || legit[i - 1][j] != 0.0)
641
+ && z[i - 1][j] <= z0) {
642
+ iLE = i - 1;
643
+ jLE = j;
644
+ iGT = i;
645
+ jGT = j;
646
+ trace_contour(z0, x, y, z, legit, dest_xs, dest_ys, gaps);
647
+ }
648
+ }
649
+ }
650
+ // Free up space.
651
+ free_space_for_curve();
652
+ FLAG(nx, ny, 2);
653
+ }
654
+
655
+ // trace_contour() -- trace_contour a contour line with high values of z to
656
+ // it's right. Stores points in (*xcurve, *ycurve) and the legit flag is
657
+ // stored in *legitcurve; initially these must be empty; you must also free
658
+ // them after this call, so that the next call will work OK.
659
+ static bool
660
+ trace_contour(double z0,
661
+ double *x,
662
+ double *y,
663
+ double **z,
664
+ double **legit,
665
+ VALUE dest_xs,
666
+ VALUE dest_ys,
667
+ VALUE gaps
668
+ )
669
+ {
670
+ int i, ii, j, jj;
671
+ double zp, vx, vy, zcentre;
672
+ int locate;
673
+ // locate tells where delta-grid point is. It codes as follows to
674
+ // i_test[] and j_test[] 6 7 8 3 4 5 0 1 2
675
+ static int i_test[9] = {
676
+ 0, 1, 1, // 6 7 8
677
+ 0, 9, 0, // 3 4 5
678
+ -1, -1, 0 // 0 1 2
679
+ };
680
+ static int j_test[9] =
681
+ {
682
+ -1, 0, 0, // 6 7 8
683
+ -1, 9, 1, // 3 4 5
684
+ 0, 0, 1 // 0 1 2
685
+ };
686
+ static int dtest[9] =
687
+ {
688
+ 0, 1, 0, // 6 7 8
689
+ 1, 0, 1, // 3 4 5
690
+ 0, 1, 0 // 0 1 2
691
+ };
692
+
693
+
694
+ // Trace the curve, storing results with append_segment() into *xcurve,
695
+ // *ycurve, *legitcurve. When done, call draw_the_contour(), which draws
696
+ // the contour stored in these arrays.
697
+ while (true) {
698
+
699
+ append_segment(x[iLE], y[jLE], z[iLE][jLE], (legit == NULL)? 1.0: legit[iLE][jLE],
700
+ x[iGT], y[jGT], z[iGT][jGT], (legit == NULL)? 1.0: legit[iGT][jGT],
701
+ z0);
702
+ // Find the next point to check through a table lookup.
703
+ locate = 3 * (jGT - jLE) + (iGT - iLE) + 4;
704
+ i = iLE + i_test[locate];
705
+ j = jLE + j_test[locate];
706
+
707
+
708
+ // Did it hit an edge?
709
+ if (i > nx_1 || i < 0 || j > ny_1 || j < 0) {
710
+ draw_the_contour(dest_xs, dest_ys, gaps);
711
+ return true; // all done
712
+ }
713
+
714
+ // Test if retracing an existing contour. See explanation
715
+ // above, in grcntour(), just before search starts.
716
+ if (locate == 5) {
717
+ int already_set = FLAG(iGT, jGT, 1);
718
+ if (already_set < 0) {
719
+ rb_raise(rb_eArgError, "ran out of storage (internal error)");
720
+ return false;
721
+ }
722
+ if (already_set) {
723
+ draw_the_contour(dest_xs, dest_ys, gaps);
724
+ return true; // all done
725
+ }
726
+ }
727
+
728
+ // Following new for 2.1.13
729
+ if (legit != NULL && legit[i][j] == 0.0) {
730
+ draw_the_contour(dest_xs, dest_ys, gaps);
731
+ return true; // all done
732
+ }
733
+
734
+ if (!dtest[locate]) {
735
+ zp = z[i][j];
736
+ if (zp > z0)
737
+ iGT = i, jGT = j;
738
+ else
739
+ iLE = i, jLE = j;
740
+ continue;
741
+ }
742
+ vx = (x[iGT] + x[i]) * 0.5;
743
+ vy = (y[jGT] + y[j]) * 0.5;
744
+ locate = 3 * (jGT - j) + iGT - i + 4;
745
+ // Fourth point in rectangular boundary
746
+ ii = i + i_test[locate];
747
+ jj = j + j_test[locate];
748
+ bool legit_diag =
749
+ (legit == NULL || (legit[iLE][jLE] != 0.0
750
+ && legit[iGT][jGT] != 0.0
751
+ && legit[i][j] != 0.0
752
+ && legit[ii][jj] != 0.0)) ? true : false;
753
+ zcentre = 0.25 * (z[iLE][jLE] + z[iGT][jGT] + z[i][j] + z[ii][jj]);
754
+
755
+ if (zcentre <= z0) {
756
+ append_segment(x[iGT], y[jGT], z[iGT][jGT], (legit == NULL)? 1.0: legit[iGT][jGT],
757
+ vx, vy, zcentre, legit_diag,
758
+ z0);
759
+ if (z[ii][jj] <= z0) {
760
+ iLE = ii, jLE = jj;
761
+ continue;
762
+ }
763
+ append_segment(x[ii], y[jj], z[ii][jj], (legit == NULL)? 1.0: legit[ii][jj],
764
+ vx, vy, zcentre, legit_diag,
765
+ z0);
766
+ if (z[i][j] <= z0) {
767
+ iGT = ii, jGT = jj;
768
+ iLE = i, jLE = j;
769
+ continue;
770
+ }
771
+ append_segment(x[i], y[j], z[i][j], (legit == NULL)? 1.0: legit[i][j],
772
+ vx, vy, zcentre, legit_diag,
773
+ z0);
774
+ iGT = i, jGT = j;
775
+ continue;
776
+ }
777
+ append_segment(vx, vy, zcentre, legit_diag,
778
+ x[iLE], y[jLE], z[iLE][jLE], (legit == NULL)? 1.0: legit[iLE][jLE],
779
+ z0);
780
+ if (z[i][j] > z0) {
781
+ iGT = i, jGT = j;
782
+ continue;
783
+ }
784
+ append_segment(vx, vy, zcentre, legit_diag,
785
+ x[i], y[j], z[i][j], (legit == NULL)? 1.0: legit[i][j],
786
+ z0);
787
+ if (z[ii][jj] <= z0) {
788
+ append_segment(vx, vy, zcentre, legit_diag,
789
+ x[ii], y[jj], z[ii][jj], (legit == NULL)? 1.0: legit[ii][jj],
790
+ z0);
791
+ iLE = ii;
792
+ jLE = jj;
793
+ continue;
794
+ }
795
+ iLE = i;
796
+ jLE = j;
797
+ iGT = ii;
798
+ jGT = jj;
799
+ }
800
+ }
801
+
802
+ // append_segment() -- append a line segment on the contour
803
+ static double xplot_last, yplot_last;
804
+ static int
805
+ append_segment(double xr, double yr, double zr, double OKr,
806
+ double xs, double ys, double zs, double OKs,
807
+ double z0)
808
+ {
809
+ if (zr == zs) rb_raise(rb_eArgError, "Contouring problem: zr = zs, which is illegal");
810
+ double frac = (zr - z0) / (zr - zs);
811
+ if (frac < 0.0) rb_raise(rb_eArgError, "Contouring problem: frac < 0");
812
+ if (frac > 1.0) rb_raise(rb_eArgError, "Contouring problem: frac > 1");
813
+ double xplot = xr - frac * (xr - xs);
814
+ double yplot = yr - frac * (yr - ys);
815
+ // Avoid replot, which I suppose must be possible, given this code
816
+ if (num_in_curve > 0 && xplot == xplot_last && yplot == yplot_last)
817
+ return 1;
818
+ if (num_in_curve > max_in_curve - 1) {
819
+ // Get new storage if running on empty. Better to
820
+ // do this with an STL vector class
821
+ max_in_curve *= 2;
822
+ int i;
823
+ double *tmp = ALLOC_N(double, num_in_curve);
824
+ for (i = 0; i < num_in_curve; i++) tmp[i] = xcurve[i];
825
+ free(xcurve); xcurve = ALLOC_N(double, max_in_curve);
826
+ for (i = 0; i < num_in_curve; i++) xcurve[i] = tmp[i];
827
+ for (i = 0; i < num_in_curve; i++) tmp[i] = ycurve[i];
828
+ free(ycurve); ycurve = ALLOC_N(double, max_in_curve);
829
+ for (i = 0; i < num_in_curve; i++) ycurve[i] = tmp[i];
830
+ free(tmp);
831
+ bool *tmpl = ALLOC_N(bool, num_in_curve);
832
+ for (i = 0; i < num_in_curve; i++) tmpl[i] = legitcurve[i];
833
+ free(legitcurve); legitcurve = ALLOC_N(bool, max_in_curve);
834
+ for (i = 0; i < num_in_curve; i++) legitcurve[i] = tmpl[i];
835
+ free(tmpl);
836
+ }
837
+ // A segment is appended only if both the present point and the last
838
+ // point came by interpolating between OK points.
839
+ xcurve[num_in_curve] = xplot;
840
+ ycurve[num_in_curve] = yplot;
841
+ if (OKr != 0.0 && OKs != 0.0)
842
+ legitcurve[num_in_curve] = true;
843
+ else
844
+ legitcurve[num_in_curve] = false;
845
+ num_in_curve++;
846
+ xplot_last = xplot;
847
+ yplot_last = yplot;
848
+ return 1;
849
+ }
850
+
851
+
852
+ // Draw contour stored in (xcurve[],ycurve[],legitcurve[]), possibly with
853
+ // labels (depending on global Label_contours).
854
+ //
855
+ // CONTOUR_VALUE MISSING_VALUE
856
+ #define FACTOR 3.0 // contour must be FACTOR*len long to be labelled
857
+ static void
858
+ draw_the_contour(
859
+ VALUE dest_xs,
860
+ VALUE dest_ys,
861
+ VALUE gaps)
862
+ {
863
+ if (num_in_curve == 1) {
864
+ num_in_curve = 0;
865
+ return;
866
+ }
867
+ int i, k;
868
+ for (i = 0, k = 0; i < num_in_curve; i++) {
869
+ if (legitcurve[i] == true) {
870
+ // PUSH_POINT does num_in_path++
871
+ PUSH_POINT(xcurve[i],ycurve[i],num_in_path);
872
+ } else {
873
+ if (num_in_path > 0 && num_in_path != k) rb_ary_push(gaps, INT2FIX(num_in_path));
874
+ k = num_in_path;
875
+ }
876
+ }
877
+ rb_ary_push(gaps, INT2FIX(num_in_path));
878
+ num_in_curve = 0;
879
+ }
880
+
881
+ // FLAG() -- check flag for gr_contour() and trace_contour()
882
+ // ni = row (or, if ind==-1, number of rows)
883
+ // nj = col (or, if ind==-1, number of cols)
884
+ // if (ind == -1), get flag storage space; initialize flags to 0
885
+ // if (ind == 1), check flag and then set it
886
+ // if (ind == 2), clear the flag storage space
887
+ // if (ind == 0), check flag, return value
888
+ // RETURN VALUE: Normally, the flag value (0 or 1). If the storage is
889
+ // exhausted, return a number <0.
890
+ #define NBITS 32
891
+ static int
892
+ FLAG(int ni, int nj, int ind)
893
+ {
894
+ static bool flag_storage_exists = false;
895
+ static unsigned long *flag, mask[NBITS];
896
+ static int size;
897
+ static int ni_max; // x-dimension is saved
898
+ int i, ipos, iword, ibit, return_value;
899
+ switch (ind) {
900
+ case -1:
901
+ // Allocate storage for flag array
902
+ if (flag_storage_exists)
903
+ rb_raise(rb_eArgError, "storage is messed up (internal error)");
904
+ size = 1 + ni * nj / NBITS; // total storage array length
905
+ flag = ALLOC_N(unsigned long, size);
906
+ // Create mask
907
+ mask[0] = 1;
908
+ for (i = 1; i < NBITS; i++)
909
+ mask[i] = 2 * mask[i - 1];
910
+ for (i = 0; i < size; i++) // Zero out flag
911
+ flag[i] = 0;
912
+ ni_max = ni; // Save for later
913
+ flag_storage_exists = true;
914
+ return 0;
915
+ case 2:
916
+ if (!flag_storage_exists)
917
+ rb_raise(rb_eArgError, "No flag storage exists");
918
+ free(flag);
919
+ flag_storage_exists = false;
920
+ return 0;
921
+ default:
922
+ if (!flag_storage_exists)
923
+ rb_raise(rb_eArgError, "No flag storage exists");
924
+ break;
925
+ }
926
+ // ind was not -1 or 2
927
+ // Find location of bit.
928
+ ipos = nj * ni_max + ni;
929
+ iword = ipos / NBITS;
930
+ ibit = ipos - iword * NBITS;
931
+ // Check for something being broken here, causing to run out of space.
932
+ // This should never happen, but may as well check.
933
+ if (iword >= size)
934
+ return (-99); // no space
935
+ // Get flag.
936
+ return_value = (0 != (*(flag + iword) & mask[ibit]));
937
+ // If ind=1 and flag wasn't set, set the flag
938
+ if (ind == 1 && !return_value)
939
+ flag[iword] |= mask[ibit];
940
+ // Return the flag value
941
+ return return_value;
942
+ }
943
+ #undef NBITS
944
+
945
+ // end of contour code from Gri
946
+
947
+
948
+
949
+ void c_make_contour(FM *p, VALUE dest_xs, VALUE dest_ys, VALUE gaps,
950
+ VALUE xs, VALUE ys, VALUE zs_data, double z_level, VALUE legit_data, int use_conrec) {
951
+ long xlen, ylen, num_columns, num_rows;
952
+ double *x_coords = Dvector_Data_for_Read(xs, &xlen);
953
+ double *y_coords = Dvector_Data_for_Read(ys, &ylen);
954
+ double **zs = Dtable_Ptr(zs_data, &num_columns, &num_rows);
955
+ double **legit = Dtable_Ptr(legit_data, &num_columns, &num_rows);
956
+ if (x_coords == NULL || gaps == Qnil || zs == NULL || y_coords == NULL) {
957
+ rb_raise(rb_eArgError, "Sorry: bad args for make_contour. Need to provide xs, ys, gaps, and zs.");
958
+ }
959
+ if (xlen != num_columns || ylen != num_rows) {
960
+ rb_raise(rb_eArgError, "Sorry: bad args for make_contour. Needs xs.size == num columns and ys.size == num rows.");
961
+ }
962
+ double x_limit, y_limit;
963
+ x_limit = 0.001*(x_coords[xlen-1] - x_coords[0])/xlen;
964
+ if (x_limit < 0) x_limit = -x_limit;
965
+ y_limit = 0.001*(y_coords[ylen-1] - y_coords[0])/ylen;
966
+ if (y_limit < 0) y_limit = -y_limit;
967
+
968
+ // NOTE: conrec data is TRANSPOSE of our data, so we switch x's and y's in the call
969
+ if (use_conrec == 1)
970
+ conrec(zs, 0, num_rows-1, 0, num_columns-1, y_coords, x_coords, 1, &z_level, dest_ys, dest_xs, gaps, y_limit, x_limit);
971
+ else
972
+ gr_contour(y_coords, x_coords, zs, legit, num_rows, num_columns, z_level, dest_ys, dest_xs, gaps);
973
+
974
+ }
975
+
976
+ VALUE FM_private_make_contour(VALUE fmkr,
977
+ VALUE dest_xs, VALUE dest_ys, VALUE gaps, // these Dvectors get the results
978
+ VALUE xs, VALUE ys, // data x coordinates and y coordinates
979
+ VALUE zs, VALUE z_level, // the Dtable of values and the desired contour level
980
+ VALUE legit, // the Dtable of flags (nonzero means okay)
981
+ VALUE method // int == 1 means CONREC
982
+ ) {
983
+ FM *p = Get_FM(fmkr);
984
+ z_level = rb_Float(z_level);
985
+ c_make_contour(p, dest_xs, dest_ys, gaps, xs, ys, zs, NUM2DBL(z_level), legit, NUM2INT(method));
986
+ return fmkr;
987
+ }
988
+
989
+