tioga 1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Tioga_README +372 -0
- data/lgpl.txt +504 -0
- data/split/Dtable/defs.h +33 -0
- data/split/Dtable/dtable.c +1928 -0
- data/split/Dtable/dtable_intern.h +144 -0
- data/split/Dtable/dvector.h +61 -0
- data/split/Dtable/extconf.rb +4 -0
- data/split/Dtable/include/dtable.h +35 -0
- data/split/Dtable/lib/Dtable_extras.rb +90 -0
- data/split/Dtable/namespace.h +47 -0
- data/split/Dtable/safe_double.h +104 -0
- data/split/Dtable/symbols.c +92 -0
- data/split/Dtable/symbols.h +52 -0
- data/split/Dvector/defs.h +33 -0
- data/split/Dvector/dvector.c +5486 -0
- data/split/Dvector/dvector_intern.h +142 -0
- data/split/Dvector/extconf.rb +4 -0
- data/split/Dvector/include/dvector.h +61 -0
- data/split/Dvector/lib/Dvector_extras.rb +328 -0
- data/split/Dvector/lib/Numeric_extras.rb +134 -0
- data/split/Dvector/namespace.h +47 -0
- data/split/Dvector/safe_double.h +104 -0
- data/split/Dvector/symbols.c +92 -0
- data/split/Dvector/symbols.h +52 -0
- data/split/Flate/defs.h +33 -0
- data/split/Flate/extconf.rb +19 -0
- data/split/Flate/flate.c +156 -0
- data/split/Flate/flate_intern.h +97 -0
- data/split/Flate/include/flate.h +98 -0
- data/split/Flate/namespace.h +47 -0
- data/split/Flate/safe_double.h +104 -0
- data/split/Flate/symbols.c +92 -0
- data/split/Flate/symbols.h +52 -0
- data/split/Function/defs.h +33 -0
- data/split/Function/dvector.h +61 -0
- data/split/Function/extconf.rb +4 -0
- data/split/Function/function.c +988 -0
- data/split/Function/joint_qsort.c +258 -0
- data/split/Function/lib/Function_extras.rb +44 -0
- data/split/Function/namespace.h +47 -0
- data/split/Function/safe_double.h +104 -0
- data/split/Function/symbols.c +92 -0
- data/split/Function/symbols.h +52 -0
- data/split/Tioga/axes.c +774 -0
- data/split/Tioga/defs.h +33 -0
- data/split/Tioga/dtable.h +35 -0
- data/split/Tioga/dvector.h +61 -0
- data/split/Tioga/extconf.rb +4 -0
- data/split/Tioga/figures.c +672 -0
- data/split/Tioga/figures.h +855 -0
- data/split/Tioga/flate.h +98 -0
- data/split/Tioga/init.c +524 -0
- data/split/Tioga/lib/Arcs_and_Circles.rb +64 -0
- data/split/Tioga/lib/ColorConstants.rb +274 -0
- data/split/Tioga/lib/Colorbars.rb +10 -0
- data/split/Tioga/lib/Colormaps.rb +105 -0
- data/split/Tioga/lib/Coordinate_Conversions.rb +194 -0
- data/split/Tioga/lib/Creating_Paths.rb +94 -0
- data/split/Tioga/lib/Doc.rb +91 -0
- data/split/Tioga/lib/Executive.rb +515 -0
- data/split/Tioga/lib/FigMkr.rb +2224 -0
- data/split/Tioga/lib/FigureConstants.rb +125 -0
- data/split/Tioga/lib/Figures_and_Plots.rb +268 -0
- data/split/Tioga/lib/Images.rb +278 -0
- data/split/Tioga/lib/Legends.rb +190 -0
- data/split/Tioga/lib/MarkerConstants.rb +122 -0
- data/split/Tioga/lib/Markers.rb +129 -0
- data/split/Tioga/lib/Page_Frame_Bounds.rb +567 -0
- data/split/Tioga/lib/Rectangles.rb +94 -0
- data/split/Tioga/lib/Shading.rb +100 -0
- data/split/Tioga/lib/Special_Paths.rb +307 -0
- data/split/Tioga/lib/Strokes.rb +129 -0
- data/split/Tioga/lib/TeX_Text.rb +454 -0
- data/split/Tioga/lib/TexPreamble.rb +358 -0
- data/split/Tioga/lib/Titles_and_Labels.rb +306 -0
- data/split/Tioga/lib/Transparency.rb +89 -0
- data/split/Tioga/lib/Using_Paths.rb +164 -0
- data/split/Tioga/lib/Utils.rb +74 -0
- data/split/Tioga/lib/X_and_Y_Axes.rb +749 -0
- data/split/Tioga/lib/irb_tioga.rb +122 -0
- data/split/Tioga/lib/tioga.rb +1 -0
- data/split/Tioga/lib/tioga_ui.rb +5 -0
- data/split/Tioga/lib/tioga_ui_cmds.rb +793 -0
- data/split/Tioga/makers.c +989 -0
- data/split/Tioga/mk_tioga_sty.rb +53 -0
- data/split/Tioga/namespace.h +47 -0
- data/split/Tioga/pdf_font_dicts.c +18253 -0
- data/split/Tioga/pdfcolor.c +486 -0
- data/split/Tioga/pdfcoords.c +505 -0
- data/split/Tioga/pdffile.c +342 -0
- data/split/Tioga/pdfimage.c +536 -0
- data/split/Tioga/pdfpath.c +914 -0
- data/split/Tioga/pdfs.h +229 -0
- data/split/Tioga/pdftext.c +443 -0
- data/split/Tioga/safe_double.h +104 -0
- data/split/Tioga/symbols.c +92 -0
- data/split/Tioga/symbols.h +52 -0
- data/split/Tioga/texout.c +380 -0
- data/split/defs.h +33 -0
- data/split/extconf.rb +107 -0
- data/split/mkmf2.rb +1612 -0
- data/split/namespace.h +47 -0
- data/split/safe_double.h +104 -0
- data/split/scripts/tioga +4 -0
- data/split/symbols.c +92 -0
- data/split/symbols.h +52 -0
- data/tests/dtable_test.data +6 -0
- data/tests/dvector_read_test.data +1 -0
- data/tests/dvector_test.data +101 -0
- data/tests/tc_Dtable.rb +221 -0
- data/tests/tc_Dvector.rb +791 -0
- data/tests/tc_FMkr.rb +162 -0
- data/tests/tc_Flate.rb +45 -0
- data/tests/tc_Function.rb +111 -0
- data/tests/ts_Tioga.rb +38 -0
- 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
|
+
|