tioga 1.7 → 1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Tioga_README +45 -29
- data/split/Dvector/dvector.c +1 -1
- data/split/Tioga/{shared/axes.c → axes.c} +360 -36
- data/split/Tioga/figures.c +2 -1
- data/split/Tioga/figures.h +6 -2
- data/split/Tioga/generic.h +0 -1
- data/split/Tioga/lib/FigMkr.rb +3 -1
- data/split/Tioga/lib/X_and_Y_Axes.rb +74 -4
- data/split/Tioga/makers.c +1303 -0
- data/split/Tioga/{shared/pdf_font_dicts.c → pdf_font_dicts.c} +0 -0
- data/split/Tioga/{shared/pdfcolor.c → pdfcolor.c} +304 -145
- data/split/Tioga/pdfcoords.c +534 -0
- data/split/Tioga/{shared/pdffile.c → pdffile.c} +161 -56
- data/split/Tioga/{shared/pdfimage.c → pdfimage.c} +171 -74
- data/split/Tioga/{shared/pdfpath.c → pdfpath.c} +0 -0
- data/split/Tioga/{shared/pdftext.c → pdftext.c} +245 -138
- data/split/Tioga/{shared/texout.c → texout.c} +18 -9
- data/split/Tioga/wrappers.c +23 -7
- data/split/Tioga/wrappers.h +5 -3
- data/split/extconf.rb +1 -1
- metadata +25 -25
- data/split/Tioga/shared/makers.c +0 -1220
- data/split/Tioga/shared/pdfcoords.c +0 -443
@@ -166,12 +166,21 @@ static void Convert_Frame_Text_Position_To_Output_Location(FM *p, int frame_side
|
|
166
166
|
}
|
167
167
|
*xp = p->page_left + page_x; *yp = p->page_bottom + page_y;
|
168
168
|
}
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
169
|
+
|
170
|
+
|
171
|
+
void c_show_rotated_text(OBJ_PTR fmkr, FM *p, char *text, int frame_side,
|
172
|
+
double shift, double fraction, double scale,
|
173
|
+
double angle, int justification, int alignment,
|
174
|
+
OBJ_PTR measure_name, int *ierr)
|
175
|
+
{
|
176
|
+
double x = 0, y = 0, base_angle = 0;
|
177
|
+
double ft_ht = p->default_text_scale * scale * p->default_font_size;
|
178
|
+
Convert_Frame_Text_Position_To_Output_Location(p, frame_side,
|
179
|
+
shift * ft_ht * ENLARGE,
|
180
|
+
fraction, &x, &y,
|
181
|
+
&base_angle, text, ierr);
|
182
|
+
tex_show_rotated_text(fmkr, p, text, x, y, scale, angle + base_angle,
|
183
|
+
justification, alignment, measure_name);
|
175
184
|
}
|
176
185
|
|
177
186
|
|
@@ -384,8 +393,8 @@ void private_make_portfolio(char *name, OBJ_PTR fignums, OBJ_PTR fignames, int *
|
|
384
393
|
Takes sizes in bp.
|
385
394
|
|
386
395
|
*/
|
387
|
-
void
|
388
|
-
|
396
|
+
void c_private_save_measure(OBJ_PTR fmkr, OBJ_PTR measure_name,
|
397
|
+
double width, double height, double depth)
|
389
398
|
{
|
390
399
|
double angle, scale;
|
391
400
|
int just, align;
|
@@ -506,7 +515,7 @@ void c_save_measure(OBJ_PTR fmkr, OBJ_PTR measure_name,
|
|
506
515
|
of arrays (xy) of doubles
|
507
516
|
*/
|
508
517
|
OBJ_PTR points = Array_New(0);
|
509
|
-
OBJ_PTR current_point;
|
518
|
+
OBJ_PTR current_point = NULL;
|
510
519
|
int i;
|
511
520
|
for(i = 0; i < 8; i++) {
|
512
521
|
char buf[4];
|
data/split/Tioga/wrappers.c
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
/* -*- c-basic-offset: 3; -*- */
|
1
2
|
/* wrappers.c */
|
2
3
|
/*
|
3
4
|
Copyright (C) 2007 Bill Paxton
|
5
|
+
(C) 2008 Vincent Fourmond
|
4
6
|
|
5
7
|
This file is part of Tioga.
|
6
8
|
|
@@ -29,7 +31,15 @@
|
|
29
31
|
|
30
32
|
// axes.c
|
31
33
|
OBJ_PTR FM_show_axis(OBJ_PTR fmkr, OBJ_PTR loc) { int ierr=0;
|
32
|
-
|
34
|
+
/* Now choosing between c_show_axis_generic and c_show_axis */
|
35
|
+
if(Is_Kind_of_Integer(loc)) /* A simple location */
|
36
|
+
c_show_axis(fmkr, Get_FM(fmkr, &ierr),
|
37
|
+
Number_to_int(loc, &ierr), &ierr);
|
38
|
+
else /* A hash */
|
39
|
+
c_show_axis_generic(fmkr, Get_FM(fmkr, &ierr), loc, &ierr);
|
40
|
+
RETURN_NIL;
|
41
|
+
}
|
42
|
+
|
33
43
|
OBJ_PTR FM_show_edge(OBJ_PTR fmkr, OBJ_PTR loc) { int ierr=0;
|
34
44
|
c_show_edge(fmkr, Get_FM(fmkr, &ierr), Number_to_int(loc, &ierr), &ierr); RETURN_NIL; }
|
35
45
|
OBJ_PTR FM_no_title(OBJ_PTR fmkr) { int ierr=0; c_no_title(fmkr, Get_FM(fmkr, &ierr), &ierr); RETURN_NIL; }
|
@@ -42,6 +52,12 @@ OBJ_PTR FM_no_right_edge(OBJ_PTR fmkr) { int ierr=0; c_no_right_edge(fmkr, Get_F
|
|
42
52
|
OBJ_PTR FM_no_top_edge(OBJ_PTR fmkr) { int ierr=0; c_no_top_edge(fmkr, Get_FM(fmkr, &ierr), &ierr); RETURN_NIL; }
|
43
53
|
OBJ_PTR FM_no_bottom_edge(OBJ_PTR fmkr) { int ierr=0; c_no_bottom_edge(fmkr, Get_FM(fmkr, &ierr), &ierr); RETURN_NIL;}
|
44
54
|
|
55
|
+
OBJ_PTR FM_axis_information(OBJ_PTR fmkr, OBJ_PTR spec)
|
56
|
+
{
|
57
|
+
int ierr=0;
|
58
|
+
return c_axis_get_information(fmkr, Get_FM(fmkr, &ierr), spec, &ierr);
|
59
|
+
}
|
60
|
+
|
45
61
|
// init.c
|
46
62
|
OBJ_PTR FM_private_init_fm_data(OBJ_PTR fmkr) { int ierr=0;
|
47
63
|
c_private_init_fm_data(fmkr, Get_FM(fmkr, &ierr), &ierr); RETURN_NIL; }
|
@@ -477,13 +493,13 @@ OBJ_PTR FM_check_label_clip(OBJ_PTR fmkr, OBJ_PTR xloc, OBJ_PTR yloc) { int ierr
|
|
477
493
|
return c_check_label_clip(fmkr, Get_FM(fmkr, &ierr), Number_to_double(xloc, &ierr), Number_to_double(yloc, &ierr), &ierr); }
|
478
494
|
|
479
495
|
|
480
|
-
OBJ_PTR
|
481
|
-
|
496
|
+
OBJ_PTR FM_private_save_measure(OBJ_PTR fmkr, OBJ_PTR measure_name,
|
497
|
+
OBJ_PTR width, OBJ_PTR height, OBJ_PTR depth)
|
482
498
|
{
|
483
499
|
int ierr;
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
500
|
+
c_private_save_measure(fmkr, measure_name,
|
501
|
+
Number_to_double(width,&ierr),
|
502
|
+
Number_to_double(height,&ierr),
|
503
|
+
Number_to_double(depth,&ierr));
|
488
504
|
return OBJ_NIL;
|
489
505
|
}
|
data/split/Tioga/wrappers.h
CHANGED
@@ -45,6 +45,8 @@ extern OBJ_PTR FM_no_left_edge(OBJ_PTR fmkr);
|
|
45
45
|
extern OBJ_PTR FM_no_right_edge(OBJ_PTR fmkr);
|
46
46
|
extern OBJ_PTR FM_no_top_edge(OBJ_PTR fmkr);
|
47
47
|
extern OBJ_PTR FM_no_bottom_edge(OBJ_PTR fmkr);
|
48
|
+
extern OBJ_PTR FM_axis_information(OBJ_PTR fmkr, OBJ_PTR loc);
|
49
|
+
|
48
50
|
|
49
51
|
/*======================================================================*/
|
50
52
|
// init.c
|
@@ -250,9 +252,9 @@ extern OBJ_PTR FM_check_label_clip(OBJ_PTR fmkr, OBJ_PTR xloc, OBJ_PTR yloc);
|
|
250
252
|
|
251
253
|
|
252
254
|
/* For saving results of text measurements. */
|
253
|
-
extern OBJ_PTR
|
254
|
-
|
255
|
-
|
255
|
+
extern OBJ_PTR FM_private_save_measure(OBJ_PTR fmkr, OBJ_PTR measure_name,
|
256
|
+
OBJ_PTR width, OBJ_PTR height,
|
257
|
+
OBJ_PTR depth);
|
256
258
|
|
257
259
|
|
258
260
|
#endif /* __wrappers_H__ */
|
data/split/extconf.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tioga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "1.
|
4
|
+
version: "1.8"
|
5
5
|
platform: ruby
|
6
6
|
authors: []
|
7
7
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: split/scripts
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-04-05 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -28,29 +28,28 @@ extra_rdoc_files: []
|
|
28
28
|
files:
|
29
29
|
- split/Tioga/wrappers.c
|
30
30
|
- split/Tioga/init.c
|
31
|
-
- split/Tioga/shared/pdf_font_dicts.c
|
32
|
-
- split/Tioga/shared/pdfcoords.c
|
33
|
-
- split/Tioga/shared/pdftext.c
|
34
|
-
- split/Tioga/shared/axes.c
|
35
|
-
- split/Tioga/shared/makers.c
|
36
|
-
- split/Tioga/shared/pdfpath.c
|
37
|
-
- split/Tioga/shared/pdfcolor.c
|
38
|
-
- split/Tioga/shared/texout.c
|
39
|
-
- split/Tioga/shared/pdffile.c
|
40
|
-
- split/Tioga/shared/pdfimage.c
|
41
31
|
- split/Tioga/figures.c
|
42
32
|
- split/Tioga/generic.c
|
33
|
+
- split/Tioga/pdf_font_dicts.c
|
34
|
+
- split/Tioga/pdfcoords.c
|
35
|
+
- split/Tioga/pdftext.c
|
36
|
+
- split/Tioga/axes.c
|
37
|
+
- split/Tioga/makers.c
|
38
|
+
- split/Tioga/pdfpath.c
|
39
|
+
- split/Tioga/pdfcolor.c
|
40
|
+
- split/Tioga/texout.c
|
41
|
+
- split/Tioga/pdffile.c
|
42
|
+
- split/Tioga/pdfimage.c
|
43
43
|
- split/Function/function.c
|
44
44
|
- split/Function/joint_qsort.c
|
45
45
|
- split/Dvector/dvector.c
|
46
46
|
- split/Dtable/dtable.c
|
47
47
|
- split/Flate/flate.c
|
48
|
-
- split/symbols.c
|
49
48
|
- split/Tioga/generic.h
|
50
49
|
- split/Tioga/pdfs.h
|
51
50
|
- split/Tioga/wrappers.h
|
52
|
-
- split/Tioga/figures.h
|
53
51
|
- split/Tioga/symbols.h
|
52
|
+
- split/Tioga/figures.h
|
54
53
|
- split/Tioga/defs.h
|
55
54
|
- split/Tioga/safe_double.h
|
56
55
|
- split/Tioga/namespace.h
|
@@ -62,29 +61,25 @@ files:
|
|
62
61
|
- split/Function/safe_double.h
|
63
62
|
- split/Function/namespace.h
|
64
63
|
- split/Function/dvector.h
|
65
|
-
- split/namespace.h
|
66
|
-
- split/Dvector/include/dvector.h
|
67
64
|
- split/Dvector/dvector_intern.h
|
68
65
|
- split/Dvector/symbols.h
|
69
66
|
- split/Dvector/defs.h
|
70
67
|
- split/Dvector/safe_double.h
|
71
68
|
- split/Dvector/namespace.h
|
72
|
-
- split/Dtable/include/dtable.h
|
73
|
-
- split/Dtable/dtable_intern.h
|
74
69
|
- split/Dtable/symbols.h
|
70
|
+
- split/Dtable/dtable_intern.h
|
75
71
|
- split/Dtable/defs.h
|
76
72
|
- split/Dtable/safe_double.h
|
77
73
|
- split/Dtable/namespace.h
|
78
74
|
- split/Dtable/dvector.h
|
79
|
-
- split/defs.h
|
80
|
-
- split/Flate/include/flate.h
|
81
|
-
- split/Flate/flate_intern.h
|
82
75
|
- split/Flate/symbols.h
|
76
|
+
- split/Flate/flate_intern.h
|
83
77
|
- split/Flate/defs.h
|
84
78
|
- split/Flate/safe_double.h
|
85
79
|
- split/Flate/namespace.h
|
86
|
-
- split/
|
87
|
-
- split/
|
80
|
+
- split/Dvector/include/dvector.h
|
81
|
+
- split/Dtable/include/dtable.h
|
82
|
+
- split/Flate/include/flate.h
|
88
83
|
- split/Tioga/lib/Rectangles.rb
|
89
84
|
- split/Tioga/lib/Colorbars.rb
|
90
85
|
- split/Tioga/lib/Shading.rb
|
@@ -113,10 +108,10 @@ files:
|
|
113
108
|
- split/Tioga/lib/tioga_ui_cmds.rb
|
114
109
|
- split/Tioga/lib/Images.rb
|
115
110
|
- split/Tioga/lib/Doc.rb
|
111
|
+
- split/Tioga/lib/TexPreamble.rb
|
116
112
|
- split/Tioga/lib/Titles_and_Labels.rb
|
117
113
|
- split/Tioga/lib/Transparency.rb
|
118
114
|
- split/Tioga/lib/ColorConstants.rb
|
119
|
-
- split/Tioga/lib/TexPreamble.rb
|
120
115
|
- split/Tioga/mk_tioga_sty.rb
|
121
116
|
- split/Tioga/extconf.rb
|
122
117
|
- split/Function/lib/Function_extras.rb
|
@@ -129,6 +124,11 @@ files:
|
|
129
124
|
- split/Flate/extconf.rb
|
130
125
|
- split/extconf.rb
|
131
126
|
- split/mkmf2.rb
|
127
|
+
- split/namespace.h
|
128
|
+
- split/defs.h
|
129
|
+
- split/symbols.h
|
130
|
+
- split/safe_double.h
|
131
|
+
- split/symbols.c
|
132
132
|
- tests/profile_Dvector
|
133
133
|
- tests/benchmark_dvector_reads.rb
|
134
134
|
- tests/dvector_read_test.data
|
@@ -163,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
163
|
version:
|
164
164
|
requirements: []
|
165
165
|
|
166
|
-
rubyforge_project:
|
166
|
+
rubyforge_project: tioga
|
167
167
|
rubygems_version: 1.0.1
|
168
168
|
signing_key:
|
169
169
|
specification_version: 2
|
data/split/Tioga/shared/makers.c
DELETED
@@ -1,1220 +0,0 @@
|
|
1
|
-
/* makers.c */
|
2
|
-
/*
|
3
|
-
Copyright (C) 2005 Bill Paxton
|
4
|
-
Copyright (C) 2007 Taro Sato
|
5
|
-
|
6
|
-
This file is part of Tioga.
|
7
|
-
|
8
|
-
Tioga is free software; you can redistribute it and/or modify
|
9
|
-
it under the terms of the GNU General Library Public License as published
|
10
|
-
by the Free Software Foundation; either version 2 of the License, or
|
11
|
-
(at your option) any later version.
|
12
|
-
|
13
|
-
Tioga is distributed in the hope that it will be useful,
|
14
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
-
GNU Library General Public License for more details.
|
17
|
-
|
18
|
-
You should have received a copy of the GNU Library General Public License
|
19
|
-
along with Tioga; if not, write to the Free Software
|
20
|
-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
21
|
-
*/
|
22
|
-
|
23
|
-
#include "figures.h"
|
24
|
-
#include "generic.h"
|
25
|
-
|
26
|
-
|
27
|
-
/* Lines */
|
28
|
-
|
29
|
-
static void create_spline_interpolant(int n_pts_data, double *Xs, double *Ys,
|
30
|
-
bool start_clamped, double start_slope, bool end_clamped, double end_slope,
|
31
|
-
double *As, double *Bs, double *Cs)
|
32
|
-
// this is copied from dvector so that makers.c won't depend on dvectors.
|
33
|
-
{
|
34
|
-
double *Hs = ALLOC_N_double(n_pts_data);
|
35
|
-
double *alphas = ALLOC_N_double(n_pts_data);
|
36
|
-
double *Ls = ALLOC_N_double(n_pts_data);
|
37
|
-
double *mu_s = ALLOC_N_double(n_pts_data);
|
38
|
-
double *Zs = ALLOC_N_double(n_pts_data);
|
39
|
-
int n = n_pts_data-1, i, j;
|
40
|
-
for (i=0; i < n; i++)
|
41
|
-
Hs[i] = Xs[i+1] - Xs[i];
|
42
|
-
if (start_clamped) alphas[0] = 3.0*(Ys[1]-Ys[0])/Hs[0] - 3.0*start_slope;
|
43
|
-
if (end_clamped) alphas[n] = 3.0*end_slope - 3.0*(Ys[n]-Ys[n-1])/Hs[n-1];
|
44
|
-
for (i=1; i < n; i++)
|
45
|
-
alphas[i] = 3.0*(Ys[i+1]*Hs[i-1]-Ys[i]*(Xs[i+1]-Xs[i-1])+Ys[i-1]*Hs[i])/(Hs[i-1]*Hs[i]);
|
46
|
-
if (start_clamped) { Ls[0] = 2.0*Hs[0]; mu_s[0] = 0.5; Zs[0] = alphas[0]/Ls[0]; }
|
47
|
-
else { Ls[0] = 1.0; mu_s[0] = 0.0; Zs[0] = 0.0; }
|
48
|
-
for (i = 1; i < n; i++) {
|
49
|
-
Ls[i] = 2.0*(Xs[i+1]-Xs[i-1]) - Hs[i-1]*mu_s[i-1];
|
50
|
-
mu_s[i] = Hs[i]/Ls[i];
|
51
|
-
Zs[i] = (alphas[i] - Hs[i-1]*Zs[i-1])/Ls[i];
|
52
|
-
}
|
53
|
-
if (end_clamped) {
|
54
|
-
Ls[n] = Hs[n-1]*(2.0-mu_s[n-1]);
|
55
|
-
Bs[n] = Zs[n] = (alphas[n]-Hs[n-1]*Zs[n-1])/Ls[n];
|
56
|
-
}
|
57
|
-
else { Ls[n] = 1.0; Zs[n] = 0.0; Bs[n] = 0.0; }
|
58
|
-
for (j = n-1; j >= 0; j--) {
|
59
|
-
Bs[j] = Zs[j] - mu_s[j]*Bs[j+1];
|
60
|
-
Cs[j] = (Ys[j+1]-Ys[j])/Hs[j] - Hs[j]*(Bs[j+1]+2.0*Bs[j])/3.0;
|
61
|
-
As[j] = (Bs[j+1]-Bs[j])/(3.0*Hs[j]);
|
62
|
-
}
|
63
|
-
free(Zs); free(mu_s); free(Ls); free(alphas); free(Hs);
|
64
|
-
}
|
65
|
-
|
66
|
-
static double spline_interpolate(double x, int n_pts_data,
|
67
|
-
double *Xs, double *Ys, double *As, double *Bs, double *Cs)
|
68
|
-
// this is copied from dvector so that makers.c won't depend on dvectors.
|
69
|
-
{
|
70
|
-
int j;
|
71
|
-
for (j = 0; j < n_pts_data && x >= Xs[j]; j++);
|
72
|
-
if (j == n_pts_data) return Ys[j-1];
|
73
|
-
if (j == 0) return Ys[0];
|
74
|
-
j--;
|
75
|
-
double dx = x - Xs[j];
|
76
|
-
return Ys[j] + dx*(Cs[j] + dx*(Bs[j] + dx*As[j]));
|
77
|
-
}
|
78
|
-
|
79
|
-
|
80
|
-
OBJ_PTR c_private_make_spline_interpolated_points(OBJ_PTR fmkr, FM *p,
|
81
|
-
OBJ_PTR Xvec, OBJ_PTR Xvec_data, OBJ_PTR Yvec_data,
|
82
|
-
OBJ_PTR start_slope, OBJ_PTR end_slope, int *ierr) {
|
83
|
-
|
84
|
-
bool start_clamped = (start_slope != OBJ_NIL), end_clamped = (end_slope != OBJ_NIL);
|
85
|
-
long xlen;
|
86
|
-
double start=0, end=0, *Ys;
|
87
|
-
double *Xs = Vector_Data_for_Read(Xvec, &xlen, ierr);
|
88
|
-
if (*ierr != 0) RETURN_NIL;
|
89
|
-
OBJ_PTR Yvec;
|
90
|
-
|
91
|
-
if (start_clamped) start = Number_to_double(start_slope, ierr);
|
92
|
-
if (end_clamped) end = Number_to_double(end_slope, ierr);
|
93
|
-
if (*ierr != 0) RETURN_NIL;
|
94
|
-
|
95
|
-
Ys = ALLOC_N_double(xlen); // Ys are same length as Xs
|
96
|
-
|
97
|
-
int i, n_pts_data;
|
98
|
-
double *As, *Bs, *Cs, *Ds;
|
99
|
-
long xdlen, ydlen;
|
100
|
-
double *X_data = Vector_Data_for_Read(Xvec_data, &xdlen, ierr);
|
101
|
-
if (*ierr != 0) RETURN_NIL;
|
102
|
-
double *Y_data = Vector_Data_for_Read(Yvec_data, &ydlen, ierr);
|
103
|
-
if (*ierr != 0) RETURN_NIL;
|
104
|
-
if (Xs == NULL || Ys == NULL || X_data == NULL || Y_data == NULL || xdlen != ydlen) {
|
105
|
-
RAISE_ERROR("Sorry: bad args",ierr); RETURN_NIL;
|
106
|
-
}
|
107
|
-
if (xlen == 0) RETURN_NIL;
|
108
|
-
n_pts_data = xdlen;
|
109
|
-
As = Y_data;
|
110
|
-
Bs = ALLOC_N_double(n_pts_data);
|
111
|
-
Cs = ALLOC_N_double(n_pts_data);
|
112
|
-
Ds = ALLOC_N_double(n_pts_data);
|
113
|
-
create_spline_interpolant(n_pts_data, X_data, Y_data,
|
114
|
-
start_clamped, start, end_clamped, end, Bs, Cs, Ds);
|
115
|
-
for (i = 0; i < xlen; i++)
|
116
|
-
Ys[i] = spline_interpolate(Xs[i], n_pts_data, X_data, As, Bs, Cs, Ds);
|
117
|
-
free(Ds); free(Cs); free(Bs);
|
118
|
-
Yvec = Vector_New(xlen, Ys);
|
119
|
-
free(Ys);
|
120
|
-
return Yvec;
|
121
|
-
}
|
122
|
-
|
123
|
-
|
124
|
-
/*
|
125
|
-
* Make points xs and ys to define a step function. x_data and y_data
|
126
|
-
* are arrays from which the step functions are generated. (xfirst,
|
127
|
-
* yfirst) and (xlast, ylast) are extra data points to fix the first
|
128
|
-
* and last steps. The x_data plus xfirst and xlast determine the
|
129
|
-
* widths of the steps. The y_data plus yfirst and ylast determine
|
130
|
-
* the height of the steps. For CENTERED justification, the steps
|
131
|
-
* occur at locations midway between the given x locations. For
|
132
|
-
* LEFT_JUSTIFIED, (x_data[i], y_data[i]) and (x_data[i], y_data[i+1])
|
133
|
-
* specifies where steps occurs. For RIGHT_JUSTIFIED, (x_data[i],
|
134
|
-
* y_data[i]) and (x_data[i], y_data[i-1]) specifies where steps
|
135
|
-
* occurs.
|
136
|
-
*
|
137
|
-
* Aug 24, 2007:
|
138
|
-
*
|
139
|
-
* TS added 'justification' to control the justification of steps.
|
140
|
-
* The use of [xy]first and [xy]last might need improvement.
|
141
|
-
*/
|
142
|
-
static void
|
143
|
-
c_make_steps(FM *p,
|
144
|
-
long *xsteps_len_ptr, double **xs_ptr,
|
145
|
-
long *ysteps_len_ptr, double **ys_ptr,
|
146
|
-
OBJ_PTR xvec_data, OBJ_PTR yvec_data,
|
147
|
-
double xfirst, double yfirst, double xlast, double ylast,
|
148
|
-
int justification, int *ierr)
|
149
|
-
{
|
150
|
-
double xnext, xprev, x;
|
151
|
-
long i, j, length, xdlen, ydlen;
|
152
|
-
double *xs = NULL, *ys = NULL;
|
153
|
-
double *x_data = Vector_Data_for_Read(xvec_data, &xdlen, ierr);
|
154
|
-
if (*ierr != 0) return;
|
155
|
-
double *y_data = Vector_Data_for_Read(yvec_data, &ydlen, ierr);
|
156
|
-
if (*ierr != 0) return;
|
157
|
-
if (x_data == NULL || y_data == NULL || xdlen != ydlen) {
|
158
|
-
RAISE_ERROR("Sorry: bad args for make_steps", ierr);
|
159
|
-
return;
|
160
|
-
}
|
161
|
-
|
162
|
-
// allocate memory for arrays to be returned
|
163
|
-
length = 2 * (xdlen + 1) + ((justification != CENTERED) ? 1 : 0);
|
164
|
-
|
165
|
-
*xsteps_len_ptr = length;
|
166
|
-
xs = ALLOC_N_double(length);
|
167
|
-
*xs_ptr = xs;
|
168
|
-
|
169
|
-
*ysteps_len_ptr = length;
|
170
|
-
ys = ALLOC_N_double(length);
|
171
|
-
*ys_ptr = ys;
|
172
|
-
|
173
|
-
// fill the arrays
|
174
|
-
switch (justification) {
|
175
|
-
case CENTERED:
|
176
|
-
for (i = 0, j = 0; i <= xdlen; ++i, j += 2) {
|
177
|
-
xprev = (i == 0) ? xfirst : x_data[i - 1];
|
178
|
-
xnext = (i == xdlen) ? xlast : x_data[i];
|
179
|
-
x = 0.5 * (xprev + xnext);
|
180
|
-
xs[j] = xs[j + 1] = x;
|
181
|
-
}
|
182
|
-
ys[0] = yfirst;
|
183
|
-
for (i = 0, j = 1; i < xdlen; ++i, j += 2) {
|
184
|
-
ys[j] = ys[j + 1] = y_data[i];
|
185
|
-
}
|
186
|
-
ys[length - 1] = ylast;
|
187
|
-
break;
|
188
|
-
case LEFT_JUSTIFIED:
|
189
|
-
xs[0] = xfirst;
|
190
|
-
for (i = 0, j = 1; i <= xdlen; ++i, j += 2) {
|
191
|
-
xs[j] = xs[j + 1] = (i == xdlen) ? xlast : x_data[i];
|
192
|
-
}
|
193
|
-
ys[0] = ys[1] = yfirst;
|
194
|
-
for (i = 0, j = 2; i < xdlen; ++i, j += 2) {
|
195
|
-
ys[j] = ys[j + 1] = y_data[i];
|
196
|
-
}
|
197
|
-
ys[length - 1] = ylast;
|
198
|
-
break;
|
199
|
-
case RIGHT_JUSTIFIED:
|
200
|
-
for (i = 0, j = 0; i <= xdlen; ++i, j += 2) {
|
201
|
-
xs[j] = xs[j + 1] = (i == 0) ? xfirst : x_data[i - 1];
|
202
|
-
}
|
203
|
-
xs[length - 1] = xlast;
|
204
|
-
ys[0] = yfirst;
|
205
|
-
for (i = 0, j = 1; i <= xdlen; ++i, j += 2) {
|
206
|
-
ys[j] = ys[j + 1] = (i == xdlen) ? ylast : y_data[i];
|
207
|
-
}
|
208
|
-
break;
|
209
|
-
default:
|
210
|
-
RAISE_ERROR_i("Sorry: unsupported justification specified (%d)",
|
211
|
-
justification, ierr);
|
212
|
-
return;
|
213
|
-
}
|
214
|
-
|
215
|
-
/* TS: I don't understand the use of the macro USE_P here, which
|
216
|
-
translates to p = NULL; For now, I'll comment out. */
|
217
|
-
//USE_P
|
218
|
-
}
|
219
|
-
|
220
|
-
|
221
|
-
OBJ_PTR
|
222
|
-
c_private_make_steps(OBJ_PTR fmkr, FM *p, OBJ_PTR xvec_data, OBJ_PTR yvec_data,
|
223
|
-
double xfirst, double yfirst, double xlast, double ylast,
|
224
|
-
int justification, int *ierr)
|
225
|
-
{
|
226
|
-
OBJ_PTR xvec;
|
227
|
-
OBJ_PTR yvec;
|
228
|
-
OBJ_PTR pts_array;
|
229
|
-
long xsteps_len = 0, ysteps_len = 0;
|
230
|
-
double *xsteps_data = NULL, *ysteps_data = NULL;
|
231
|
-
|
232
|
-
c_make_steps(p, &xsteps_len, &xsteps_data, &ysteps_len, &ysteps_data,
|
233
|
-
xvec_data, yvec_data, xfirst, yfirst, xlast, ylast,
|
234
|
-
justification, ierr);
|
235
|
-
if (*ierr != 0) RETURN_NIL;
|
236
|
-
|
237
|
-
xvec = Vector_New(xsteps_len, xsteps_data);
|
238
|
-
yvec = Vector_New(ysteps_len, ysteps_data);
|
239
|
-
free(xsteps_data);
|
240
|
-
free(ysteps_data);
|
241
|
-
|
242
|
-
pts_array = Array_New(2);
|
243
|
-
Array_Store(pts_array, 0, xvec, ierr);
|
244
|
-
if (*ierr != 0) RETURN_NIL;
|
245
|
-
Array_Store(pts_array, 1, yvec, ierr);
|
246
|
-
if (*ierr != 0) RETURN_NIL;
|
247
|
-
return pts_array;
|
248
|
-
}
|
249
|
-
|
250
|
-
|
251
|
-
/*
|
252
|
-
CONREC: A Contouring Subroutine
|
253
|
-
written by Paul Bourke
|
254
|
-
see: http://astronomy.swin.edu.au/~pbourke/projection/conrec/
|
255
|
-
|
256
|
-
Copyright (c) 1996-1997 Nicholas Yue
|
257
|
-
|
258
|
-
This software is copyrighted by Nicholas Yue. This code is base on the work of
|
259
|
-
Paul D. Bourke CONREC.F routine
|
260
|
-
|
261
|
-
The authors hereby grant permission to use, copy, and distribute this
|
262
|
-
software and its documentation for any purpose, provided that existing
|
263
|
-
copyright notices are retained in all copies and that this notice is included
|
264
|
-
verbatim in any distributions. Additionally, the authors grant permission to
|
265
|
-
modify this software and its documentation for any purpose, provided that
|
266
|
-
such modifications are not distributed without the explicit consent of the
|
267
|
-
authors and that existing copyright notices are retained in all copies. Some
|
268
|
-
of the algorithms implemented by this software are patented, observe all
|
269
|
-
applicable patent law.
|
270
|
-
|
271
|
-
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
|
272
|
-
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
|
273
|
-
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
|
274
|
-
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
275
|
-
|
276
|
-
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
|
277
|
-
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
278
|
-
PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN
|
279
|
-
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
280
|
-
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
281
|
-
*/
|
282
|
-
|
283
|
-
//=============================================================================
|
284
|
-
//
|
285
|
-
// CONREC is a contouring subroutine for rectangularily spaced data.
|
286
|
-
//
|
287
|
-
// It emits calls to a line drawing subroutine supplied by the user
|
288
|
-
// which draws a contour map corresponding to real*4data on a randomly
|
289
|
-
// spaced rectangular grid. The coordinates emitted are in the same
|
290
|
-
// units given in the x() and y() arrays.
|
291
|
-
//
|
292
|
-
// Any number of contour levels may be specified but they must be
|
293
|
-
// in order of increasing value.
|
294
|
-
//
|
295
|
-
// As this code is ported from FORTRAN-77, please be very careful of the
|
296
|
-
// various indices like ilb,iub,jlb and jub, remeber that C/C++ indices
|
297
|
-
// starts from zero (0)
|
298
|
-
//
|
299
|
-
//=============================================================================
|
300
|
-
#include <stdio.h>
|
301
|
-
#include <math.h>
|
302
|
-
|
303
|
-
#define xsect(p1,p2) (h[p2]*xh[p1]-h[p1]*xh[p2])/(h[p2]-h[p1])
|
304
|
-
#define ysect(p1,p2) (h[p2]*yh[p1]-h[p1]*yh[p2])/(h[p2]-h[p1])
|
305
|
-
#define min(x,y) (x<y?x:y)
|
306
|
-
#define max(x,y) (x>y?x:y)
|
307
|
-
|
308
|
-
#define PUSH_POINT(x,y) { \
|
309
|
-
if (*dest_len_ptr >= *dest_sz_ptr) { \
|
310
|
-
*dest_sz_ptr += *dest_sz_ptr + 100; \
|
311
|
-
REALLOC_double(dest_xs_ptr,*dest_sz_ptr); \
|
312
|
-
REALLOC_double(dest_ys_ptr,*dest_sz_ptr); \
|
313
|
-
} \
|
314
|
-
(*dest_xs_ptr)[*dest_len_ptr] = x; \
|
315
|
-
(*dest_ys_ptr)[*dest_len_ptr] = y; \
|
316
|
-
(*dest_len_ptr)++; \
|
317
|
-
}
|
318
|
-
|
319
|
-
static int conrec(double **d,
|
320
|
-
int ilb,
|
321
|
-
int iub,
|
322
|
-
int jlb,
|
323
|
-
int jub,
|
324
|
-
double *x,
|
325
|
-
double *y,
|
326
|
-
int nc,
|
327
|
-
double *z,
|
328
|
-
long *dest_len_ptr,
|
329
|
-
double **dest_xs_ptr,
|
330
|
-
double **dest_ys_ptr,
|
331
|
-
long *dest_sz_ptr,
|
332
|
-
OBJ_PTR gaps,
|
333
|
-
double x_limit,
|
334
|
-
double y_limit,
|
335
|
-
int *ierr)
|
336
|
-
// d ! matrix of data to contour
|
337
|
-
// ilb,iub,jlb,jub ! index bounds of data matrix
|
338
|
-
// x ! data matrix column coordinates
|
339
|
-
// y ! data matrix row coordinates
|
340
|
-
// nc ! number of contour levels
|
341
|
-
// z ! contour levels in increasing order
|
342
|
-
{
|
343
|
-
int num_pts = 0;
|
344
|
-
double x_prev=0.0, y_prev=0.0;
|
345
|
-
int m1,m2,m3,case_value;
|
346
|
-
double dmin,dmax,x1=0.0,x2=0.0,y1=0.0,y2=0.0;
|
347
|
-
register int i,j,k,m;
|
348
|
-
double h[5];
|
349
|
-
int sh[5];
|
350
|
-
double xh[5],yh[5];
|
351
|
-
//===========================================================================
|
352
|
-
// The indexing of im and jm should be noted as it has to start from zero
|
353
|
-
// unlike the fortran counter part
|
354
|
-
//===========================================================================
|
355
|
-
int im[4] = {0,1,1,0},jm[4]={0,0,1,1};
|
356
|
-
//===========================================================================
|
357
|
-
// Note that castab is arranged differently from the FORTRAN code because
|
358
|
-
// Fortran and C/C++ arrays are transposes of each other, in this case
|
359
|
-
// it is more tricky as castab is in 3 dimension
|
360
|
-
//===========================================================================
|
361
|
-
int castab[3][3][3] =
|
362
|
-
{
|
363
|
-
{
|
364
|
-
{0,0,8},{0,2,5},{7,6,9}
|
365
|
-
},
|
366
|
-
{
|
367
|
-
{0,3,4},{1,3,1},{4,3,0}
|
368
|
-
},
|
369
|
-
{
|
370
|
-
{9,6,7},{5,2,0},{8,0,0}
|
371
|
-
}
|
372
|
-
};
|
373
|
-
for (j=(jub-1);j>=jlb;j--) {
|
374
|
-
for (i=ilb;i<=iub-1;i++) {
|
375
|
-
double temp1,temp2;
|
376
|
-
temp1 = min(d[i][j],d[i][j+1]);
|
377
|
-
temp2 = min(d[i+1][j],d[i+1][j+1]);
|
378
|
-
dmin = min(temp1,temp2);
|
379
|
-
temp1 = max(d[i][j],d[i][j+1]);
|
380
|
-
temp2 = max(d[i+1][j],d[i+1][j+1]);
|
381
|
-
dmax = max(temp1,temp2);
|
382
|
-
if (dmax>=z[0]&&dmin<=z[nc-1]) {
|
383
|
-
for (k=0;k<nc;k++) {
|
384
|
-
if (z[k]>=dmin&&z[k]<=dmax) {
|
385
|
-
for (m=4;m>=0;m--) {
|
386
|
-
if (m>0) {
|
387
|
-
//=============================================================
|
388
|
-
// The indexing of im and jm should be noted as it has to
|
389
|
-
// start from zero
|
390
|
-
//=============================================================
|
391
|
-
h[m] = d[i+im[m-1]][j+jm[m-1]]-z[k];
|
392
|
-
xh[m] = x[i+im[m-1]];
|
393
|
-
yh[m] = y[j+jm[m-1]];
|
394
|
-
} else {
|
395
|
-
h[0] = 0.25*(h[1]+h[2]+h[3]+h[4]);
|
396
|
-
xh[0]=0.5*(x[i]+x[i+1]);
|
397
|
-
yh[0]=0.5*(y[j]+y[j+1]);
|
398
|
-
}
|
399
|
-
if (h[m]>0.0) {
|
400
|
-
sh[m] = 1;
|
401
|
-
} else if (h[m]<0.0) {
|
402
|
-
sh[m] = -1;
|
403
|
-
} else
|
404
|
-
sh[m] = 0;
|
405
|
-
}
|
406
|
-
//=================================================================
|
407
|
-
//
|
408
|
-
// Note: at this stage the relative heights of the corners and the
|
409
|
-
// centre are in the h array, and the corresponding coordinates are
|
410
|
-
// in the xh and yh arrays. The centre of the box is indexed by 0
|
411
|
-
// and the 4 corners by 1 to 4 as shown below.
|
412
|
-
// Each triangle is then indexed by the parameter m, and the 3
|
413
|
-
// vertices of each triangle are indexed by parameters m1,m2,and
|
414
|
-
// m3.
|
415
|
-
// It is assumed that the centre of the box is always vertex 2
|
416
|
-
// though this isimportant only when all 3 vertices lie exactly on
|
417
|
-
// the same contour level, in which case only the side of the box
|
418
|
-
// is drawn.
|
419
|
-
//
|
420
|
-
//
|
421
|
-
// vertex 4 +-------------------+ vertex 3
|
422
|
-
// | \ / |
|
423
|
-
// | \ m-3 / |
|
424
|
-
// | \ / |
|
425
|
-
// | \ / |
|
426
|
-
// | m=2 X m=2 | the centre is vertex 0
|
427
|
-
// | / \ |
|
428
|
-
// | / \ |
|
429
|
-
// | / m=1 \ |
|
430
|
-
// | / \ |
|
431
|
-
// vertex 1 +-------------------+ vertex 2
|
432
|
-
//
|
433
|
-
//
|
434
|
-
//
|
435
|
-
// Scan each triangle in the box
|
436
|
-
//
|
437
|
-
//=================================================================
|
438
|
-
for (m=1;m<=4;m++) {
|
439
|
-
m1 = m;
|
440
|
-
m2 = 0;
|
441
|
-
if (m!=4)
|
442
|
-
m3 = m+1;
|
443
|
-
else
|
444
|
-
m3 = 1;
|
445
|
-
case_value = castab[sh[m1]+1][sh[m2]+1][sh[m3]+1];
|
446
|
-
if (case_value!=0) {
|
447
|
-
switch (case_value) {
|
448
|
-
//===========================================================
|
449
|
-
// Case 1 - Line between vertices 1 and 2
|
450
|
-
//===========================================================
|
451
|
-
case 1:
|
452
|
-
x1=xh[m1];
|
453
|
-
y1=yh[m1];
|
454
|
-
x2=xh[m2];
|
455
|
-
y2=yh[m2];
|
456
|
-
break;
|
457
|
-
//===========================================================
|
458
|
-
// Case 2 - Line between vertices 2 and 3
|
459
|
-
//===========================================================
|
460
|
-
case 2:
|
461
|
-
x1=xh[m2];
|
462
|
-
y1=yh[m2];
|
463
|
-
x2=xh[m3];
|
464
|
-
y2=yh[m3];
|
465
|
-
break;
|
466
|
-
//===========================================================
|
467
|
-
// Case 3 - Line between vertices 3 and 1
|
468
|
-
//===========================================================
|
469
|
-
case 3:
|
470
|
-
x1=xh[m3];
|
471
|
-
y1=yh[m3];
|
472
|
-
x2=xh[m1];
|
473
|
-
y2=yh[m1];
|
474
|
-
break;
|
475
|
-
//===========================================================
|
476
|
-
// Case 4 - Line between vertex 1 and side 2-3
|
477
|
-
//===========================================================
|
478
|
-
case 4:
|
479
|
-
x1=xh[m1];
|
480
|
-
y1=yh[m1];
|
481
|
-
x2=xsect(m2,m3);
|
482
|
-
y2=ysect(m2,m3);
|
483
|
-
break;
|
484
|
-
//===========================================================
|
485
|
-
// Case 5 - Line between vertex 2 and side 3-1
|
486
|
-
//===========================================================
|
487
|
-
case 5:
|
488
|
-
x1=xh[m2];
|
489
|
-
y1=yh[m2];
|
490
|
-
x2=xsect(m3,m1);
|
491
|
-
y2=ysect(m3,m1);
|
492
|
-
break;
|
493
|
-
//===========================================================
|
494
|
-
// Case 6 - Line between vertex 3 and side 1-2
|
495
|
-
//===========================================================
|
496
|
-
case 6:
|
497
|
-
x1=xh[m3];
|
498
|
-
y1=yh[m3];
|
499
|
-
x2=xsect(m1,m2);
|
500
|
-
y2=ysect(m1,m2);
|
501
|
-
break;
|
502
|
-
//===========================================================
|
503
|
-
// Case 7 - Line between sides 1-2 and 2-3
|
504
|
-
//===========================================================
|
505
|
-
case 7:
|
506
|
-
x1=xsect(m1,m2);
|
507
|
-
y1=ysect(m1,m2);
|
508
|
-
x2=xsect(m2,m3);
|
509
|
-
y2=ysect(m2,m3);
|
510
|
-
break;
|
511
|
-
//===========================================================
|
512
|
-
// Case 8 - Line between sides 2-3 and 3-1
|
513
|
-
//===========================================================
|
514
|
-
case 8:
|
515
|
-
x1=xsect(m2,m3);
|
516
|
-
y1=ysect(m2,m3);
|
517
|
-
x2=xsect(m3,m1);
|
518
|
-
y2=ysect(m3,m1);
|
519
|
-
break;
|
520
|
-
//===========================================================
|
521
|
-
// Case 9 - Line between sides 3-1 and 1-2
|
522
|
-
//===========================================================
|
523
|
-
case 9:
|
524
|
-
x1=xsect(m3,m1);
|
525
|
-
y1=ysect(m3,m1);
|
526
|
-
x2=xsect(m1,m2);
|
527
|
-
y2=ysect(m1,m2);
|
528
|
-
break;
|
529
|
-
default:
|
530
|
-
break;
|
531
|
-
}
|
532
|
-
double dx = x1 - x_prev, dy = y1 - y_prev;
|
533
|
-
if (dx < 0) dx = -dx; if (dy < 0) dy = -dy;
|
534
|
-
if (num_pts == 0 || dx > x_limit || dy > y_limit) {
|
535
|
-
if (num_pts > 0) { Array_Push(gaps, Integer_New(num_pts), ierr); if (*ierr != 0) return 0; }
|
536
|
-
PUSH_POINT(x1,y1); num_pts++;
|
537
|
-
}
|
538
|
-
PUSH_POINT(x2,y2); num_pts++;
|
539
|
-
x_prev = x2; y_prev = y2;
|
540
|
-
}
|
541
|
-
}
|
542
|
-
}
|
543
|
-
}
|
544
|
-
}
|
545
|
-
}
|
546
|
-
}
|
547
|
-
return 0;
|
548
|
-
}
|
549
|
-
|
550
|
-
/* end of conrec */
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
// the following code is from Gri
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
#include <math.h>
|
565
|
-
#include <stdio.h>
|
566
|
-
#include <string.h>
|
567
|
-
|
568
|
-
// globals to this file
|
569
|
-
static int nx_1, ny_1, iGT, jGT, iLE, jLE;
|
570
|
-
|
571
|
-
static void free_space_for_curve(void);
|
572
|
-
static void get_space_for_curve(int *ierr);
|
573
|
-
static void draw_the_contour(
|
574
|
-
long *dest_len_ptr,
|
575
|
-
double **dest_xs_ptr,
|
576
|
-
double **dest_ys_ptr,
|
577
|
-
long *dest_sz_ptr,
|
578
|
-
OBJ_PTR gaps,
|
579
|
-
int *ierr);
|
580
|
-
|
581
|
-
static bool trace_contour(double z0,
|
582
|
-
double *x,
|
583
|
-
double *y,
|
584
|
-
double **z,
|
585
|
-
double **legit,
|
586
|
-
long *dest_len_ptr,
|
587
|
-
double **dest_xs_ptr,
|
588
|
-
double **dest_ys_ptr,
|
589
|
-
long *dest_sz_ptr,
|
590
|
-
OBJ_PTR gaps,
|
591
|
-
int *iterr);
|
592
|
-
|
593
|
-
static int FLAG(int ni, int nj, int ind, int *ierr);
|
594
|
-
static int append_segment(double xr, double yr, double zr, double OKr,
|
595
|
-
double xs, double ys, double zs, double OKs,
|
596
|
-
double z0, int *ierr);
|
597
|
-
|
598
|
-
// Space for curve, shared by several routines
|
599
|
-
static double *xcurve, *ycurve;
|
600
|
-
static bool *legitcurve;
|
601
|
-
#define INITIAL_CURVE_SIZE 100
|
602
|
-
static int num_in_curve, max_in_curve, num_in_path;
|
603
|
-
static bool curve_storage_exists = false;
|
604
|
-
|
605
|
-
|
606
|
-
static void
|
607
|
-
free_space_for_curve(void)
|
608
|
-
{
|
609
|
-
if (curve_storage_exists) {
|
610
|
-
free(xcurve);
|
611
|
-
free(ycurve);
|
612
|
-
free(legitcurve);
|
613
|
-
curve_storage_exists = false;
|
614
|
-
}
|
615
|
-
num_in_curve = 0;
|
616
|
-
num_in_path = 0;
|
617
|
-
}
|
618
|
-
|
619
|
-
static void
|
620
|
-
get_space_for_curve(int *ierr)
|
621
|
-
{
|
622
|
-
max_in_curve = INITIAL_CURVE_SIZE;
|
623
|
-
if(curve_storage_exists) {
|
624
|
-
RAISE_ERROR("storage is messed up (internal error)", ierr);
|
625
|
-
return;
|
626
|
-
}
|
627
|
-
xcurve = ALLOC_N_double(max_in_curve);
|
628
|
-
ycurve = ALLOC_N_double(max_in_curve);
|
629
|
-
legitcurve = ALLOC_N_bool(max_in_curve);
|
630
|
-
curve_storage_exists = true;
|
631
|
-
num_in_curve = 0;
|
632
|
-
num_in_path = 0;
|
633
|
-
}
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
// gr_contour() -- draw contour line for gridded data
|
638
|
-
//
|
639
|
-
// DESCRIPTION: Draws a contour for the value z0, through data z[i][j] defined
|
640
|
-
// on the rectangular grid x[i] and y[j] (where 0<=i<nx and 0<=j<ny). That
|
641
|
-
// the grid is rectangular but needn't be square or regular. Contours are
|
642
|
-
// drawn only in triangular regions surrounded by 3 good points (ie, 3 points
|
643
|
-
// with legit[i][j] != 0.0).
|
644
|
-
//
|
645
|
-
// The contour is labelled, with the string// lab, at intervals of
|
646
|
-
// contour_space_later centimeters, starting with a space of
|
647
|
-
// contour_space_first from the beginning of the trace.
|
648
|
-
//
|
649
|
-
static void
|
650
|
-
gr_contour(
|
651
|
-
double *x,
|
652
|
-
double *y,
|
653
|
-
double **z,
|
654
|
-
double **legit,
|
655
|
-
int nx,
|
656
|
-
int ny,
|
657
|
-
double z0,
|
658
|
-
long *dest_len_ptr,
|
659
|
-
double **dest_xs_ptr,
|
660
|
-
double **dest_ys_ptr,
|
661
|
-
long *dest_sz_ptr,
|
662
|
-
OBJ_PTR gaps,
|
663
|
-
int *ierr)
|
664
|
-
{
|
665
|
-
register int i, j;
|
666
|
-
// Test for errors
|
667
|
-
if (nx <= 0) { RAISE_ERROR("nx<=0 (internal error)", ierr); return; }
|
668
|
-
if (ny <= 0) { RAISE_ERROR("ny<=0 (internal error)", ierr); return; }
|
669
|
-
// Save some globals
|
670
|
-
nx_1 = nx - 1;
|
671
|
-
ny_1 = ny - 1;
|
672
|
-
// Clear all switches.
|
673
|
-
FLAG(nx, ny, -1, ierr);
|
674
|
-
// Get space for the curve.
|
675
|
-
get_space_for_curve(ierr);
|
676
|
-
if (*ierr != 0) return;
|
677
|
-
|
678
|
-
// Search for a contour intersecting various places on the grid. Whenever
|
679
|
-
// a contour is found to be between two grid points, call trace_contour()
|
680
|
-
// after defining the global variables iLE,jLE,iGT,jGT so that
|
681
|
-
// z[iLE]jLE] <= z0 < z[iGT][jGT], where legit[iLE][jLE] != 0
|
682
|
-
// and legit[iGT][jGT] != 0.
|
683
|
-
//
|
684
|
-
// NOTE: always start a contour running upwards (to greater j), between
|
685
|
-
// two sideways neighboring points (same j). Later, in trace_contour(),
|
686
|
-
// test 'locate' for value 5. If it's 5, it means that the same geometry
|
687
|
-
// obtains, so set a flag and check whether already set. If already
|
688
|
-
// set, it means we've traced this contour before, so trace_contour()
|
689
|
-
// knows to stop then.
|
690
|
-
|
691
|
-
// Search bottom
|
692
|
-
for (i = 1; i < nx; i++) {
|
693
|
-
j = 0;
|
694
|
-
while (j < ny_1) {
|
695
|
-
// move north to first legit point
|
696
|
-
while (j < ny_1
|
697
|
-
&& (legit == NULL || !(legit[i][j] != 0.0 && legit[i - 1][j] != 0.0))
|
698
|
-
) {
|
699
|
-
j++;
|
700
|
-
}
|
701
|
-
// trace a contour if it hits here
|
702
|
-
if (j < ny_1 && z[i][j] > z0 && z[i - 1][j] <= z0) {
|
703
|
-
iLE = i - 1;
|
704
|
-
jLE = j;
|
705
|
-
iGT = i;
|
706
|
-
jGT = j;
|
707
|
-
trace_contour(z0, x, y, z, legit, dest_len_ptr, dest_xs_ptr, dest_ys_ptr, dest_sz_ptr, gaps, ierr);
|
708
|
-
if (*ierr != 0) return;
|
709
|
-
}
|
710
|
-
// Space through legit points, that is, skipping through good
|
711
|
-
// data looking for another island of bad data which will
|
712
|
-
// thus be a new 'bottom edge'.
|
713
|
-
while (j < ny_1 && (legit == NULL || (legit[i][j] != 0.0 && legit[i - 1][j] != 0.0)))
|
714
|
-
j++;
|
715
|
-
}
|
716
|
-
}
|
717
|
-
|
718
|
-
// search right edge
|
719
|
-
for (j = 1; j < ny; j++) {
|
720
|
-
i = nx_1;
|
721
|
-
while (i > 0) {
|
722
|
-
// move west to first legit point
|
723
|
-
while (i > 0 && (legit == NULL || !(legit[i][j] != 0.0 && legit[i][ j - 1] != 0.0)))
|
724
|
-
i--;
|
725
|
-
// trace a contour if it hits here
|
726
|
-
if (i > 0 && z[i][j] > z0 && z[i][j - 1] <= z0) {
|
727
|
-
iLE = i;
|
728
|
-
jLE = j - 1;
|
729
|
-
iGT = i;
|
730
|
-
jGT = j;
|
731
|
-
trace_contour(z0, x, y, z, legit, dest_len_ptr, dest_xs_ptr, dest_ys_ptr, dest_sz_ptr, gaps, ierr);
|
732
|
-
if (*ierr != 0) return;
|
733
|
-
}
|
734
|
-
// space through legit points
|
735
|
-
while (i > 0 && (legit == NULL || (legit[i][j] != 0.0 && legit[i][ j - 1] != 0.0)))
|
736
|
-
i--;
|
737
|
-
}
|
738
|
-
}
|
739
|
-
|
740
|
-
// search top edge
|
741
|
-
for (i = nx_1 - 1; i > -1; i--) {
|
742
|
-
j = ny_1;
|
743
|
-
while (j > 0) {
|
744
|
-
while (j > 0 && (legit == NULL || !(legit[i][j] != 0.0 && legit[i + 1][ j] != 0.0)))
|
745
|
-
j--;
|
746
|
-
// trace a contour if it hits here
|
747
|
-
if (j > 0 && z[i][j] > z0 && z[i + 1][ j] <= z0) {
|
748
|
-
iLE = i + 1;
|
749
|
-
jLE = j;
|
750
|
-
iGT = i;
|
751
|
-
jGT = j;
|
752
|
-
trace_contour(z0, x, y, z, legit, dest_len_ptr, dest_xs_ptr, dest_ys_ptr, dest_sz_ptr, gaps, ierr);
|
753
|
-
if (*ierr != 0) return;
|
754
|
-
}
|
755
|
-
// space through legit points
|
756
|
-
while (j > 0 && (legit == NULL || (legit[i][j] != 0.0 && legit[i + 1][ j] != 0.0)))
|
757
|
-
j--;
|
758
|
-
}
|
759
|
-
}
|
760
|
-
|
761
|
-
// search left edge
|
762
|
-
for (j = ny_1 - 1; j > -1; j--) {
|
763
|
-
i = 0;
|
764
|
-
while (i < nx_1) {
|
765
|
-
while (i < nx_1 && (legit == NULL || !(legit[i][j] != 0.0 && legit[i][ j + 1] != 0.0)))
|
766
|
-
i++;
|
767
|
-
// trace a contour if it hits here
|
768
|
-
if (i < nx_1 && z[i][j] > z0 && z[i][j + 1] <= z0) {
|
769
|
-
iLE = i;
|
770
|
-
jLE = j + 1;
|
771
|
-
iGT = i;
|
772
|
-
jGT = j;
|
773
|
-
trace_contour(z0, x, y, z, legit, dest_len_ptr, dest_xs_ptr, dest_ys_ptr, dest_sz_ptr, gaps, ierr);
|
774
|
-
if (*ierr != 0) return;
|
775
|
-
}
|
776
|
-
// space through legit points
|
777
|
-
while (i < nx_1 && (legit == NULL || (legit[i][j] != 0.0 && legit[i][ j + 1] != 0.0)))
|
778
|
-
i++;
|
779
|
-
}
|
780
|
-
}
|
781
|
-
|
782
|
-
// Search interior. Pass up from bottom (starting at left), through all
|
783
|
-
// interior points. Look for contours which enter, with high to right,
|
784
|
-
// between iLE on left and iGT on right.
|
785
|
-
for (j = 1; j < ny_1; j++) {
|
786
|
-
int flag_is_set;
|
787
|
-
for (i = 1; i < nx; i++) {
|
788
|
-
// trace a contour if it hits here
|
789
|
-
flag_is_set = FLAG(i, j, 0, ierr);
|
790
|
-
if (*ierr != 0) return;
|
791
|
-
if (flag_is_set < 0) {
|
792
|
-
RAISE_ERROR("ran out of storage (internal error)", ierr);
|
793
|
-
return;
|
794
|
-
}
|
795
|
-
if (!flag_is_set
|
796
|
-
&& (legit == NULL || legit[i][j] != 0.0)
|
797
|
-
&& z[i][j] > z0
|
798
|
-
&& (legit == NULL || legit[i - 1][j] != 0.0)
|
799
|
-
&& z[i - 1][j] <= z0) {
|
800
|
-
iLE = i - 1;
|
801
|
-
jLE = j;
|
802
|
-
iGT = i;
|
803
|
-
jGT = j;
|
804
|
-
trace_contour(z0, x, y, z, legit, dest_len_ptr, dest_xs_ptr, dest_ys_ptr, dest_sz_ptr, gaps, ierr);
|
805
|
-
if (*ierr != 0) return;
|
806
|
-
}
|
807
|
-
}
|
808
|
-
}
|
809
|
-
// Free up space.
|
810
|
-
free_space_for_curve();
|
811
|
-
FLAG(nx, ny, 2, ierr);
|
812
|
-
}
|
813
|
-
|
814
|
-
// trace_contour() -- trace_contour a contour line with high values of z to
|
815
|
-
// it's right. Stores points in (*xcurve, *ycurve) and the legit flag is
|
816
|
-
// stored in *legitcurve; initially these must be empty; you must also free
|
817
|
-
// them after this call, so that the next call will work OK.
|
818
|
-
static bool
|
819
|
-
trace_contour(double z0,
|
820
|
-
double *x,
|
821
|
-
double *y,
|
822
|
-
double **z,
|
823
|
-
double **legit,
|
824
|
-
long *dest_len_ptr,
|
825
|
-
double **dest_xs_ptr,
|
826
|
-
double **dest_ys_ptr,
|
827
|
-
long *dest_sz_ptr,
|
828
|
-
OBJ_PTR gaps,
|
829
|
-
int *ierr
|
830
|
-
)
|
831
|
-
{
|
832
|
-
int i, ii, j, jj;
|
833
|
-
double zp, vx, vy, zcentre;
|
834
|
-
int locate;
|
835
|
-
// locate tells where delta-grid point is. It codes as follows to
|
836
|
-
// i_test[] and j_test[] 6 7 8 3 4 5 0 1 2
|
837
|
-
static int i_test[9] = {
|
838
|
-
0, 1, 1, // 6 7 8
|
839
|
-
0, 9, 0, // 3 4 5
|
840
|
-
-1, -1, 0 // 0 1 2
|
841
|
-
};
|
842
|
-
static int j_test[9] =
|
843
|
-
{
|
844
|
-
-1, 0, 0, // 6 7 8
|
845
|
-
-1, 9, 1, // 3 4 5
|
846
|
-
0, 0, 1 // 0 1 2
|
847
|
-
};
|
848
|
-
static int dtest[9] =
|
849
|
-
{
|
850
|
-
0, 1, 0, // 6 7 8
|
851
|
-
1, 0, 1, // 3 4 5
|
852
|
-
0, 1, 0 // 0 1 2
|
853
|
-
};
|
854
|
-
|
855
|
-
|
856
|
-
// Trace the curve, storing results with append_segment() into *xcurve,
|
857
|
-
// *ycurve, *legitcurve. When done, call draw_the_contour(), which draws
|
858
|
-
// the contour stored in these arrays.
|
859
|
-
while (true) {
|
860
|
-
|
861
|
-
append_segment(x[iLE], y[jLE], z[iLE][jLE], (legit == NULL)? 1.0: legit[iLE][jLE],
|
862
|
-
x[iGT], y[jGT], z[iGT][jGT], (legit == NULL)? 1.0: legit[iGT][jGT],
|
863
|
-
z0, ierr);
|
864
|
-
if (*ierr != 0) return false;
|
865
|
-
// Find the next point to check through a table lookup.
|
866
|
-
locate = 3 * (jGT - jLE) + (iGT - iLE) + 4;
|
867
|
-
i = iLE + i_test[locate];
|
868
|
-
j = jLE + j_test[locate];
|
869
|
-
|
870
|
-
|
871
|
-
// Did it hit an edge?
|
872
|
-
if (i > nx_1 || i < 0 || j > ny_1 || j < 0) {
|
873
|
-
draw_the_contour(dest_len_ptr, dest_xs_ptr, dest_ys_ptr, dest_sz_ptr, gaps, ierr);
|
874
|
-
if (*ierr != 0) return false;
|
875
|
-
return true; // all done
|
876
|
-
}
|
877
|
-
|
878
|
-
// Test if retracing an existing contour. See explanation
|
879
|
-
// above, in grcntour(), just before search starts.
|
880
|
-
if (locate == 5) {
|
881
|
-
int already_set = FLAG(iGT, jGT, 1, ierr);
|
882
|
-
if (*ierr != 0) return false;
|
883
|
-
if (already_set < 0) {
|
884
|
-
RAISE_ERROR("ran out of storage (internal error)", ierr);
|
885
|
-
return false;
|
886
|
-
}
|
887
|
-
if (already_set) {
|
888
|
-
draw_the_contour(dest_len_ptr, dest_xs_ptr, dest_ys_ptr, dest_sz_ptr, gaps, ierr);
|
889
|
-
if (*ierr != 0) return false;
|
890
|
-
return true; // all done
|
891
|
-
}
|
892
|
-
}
|
893
|
-
|
894
|
-
// Following new for 2.1.13
|
895
|
-
if (legit != NULL && legit[i][j] == 0.0) {
|
896
|
-
draw_the_contour(dest_len_ptr, dest_xs_ptr, dest_ys_ptr, dest_sz_ptr, gaps, ierr);
|
897
|
-
if (*ierr != 0) return false;
|
898
|
-
return true; // all done
|
899
|
-
}
|
900
|
-
|
901
|
-
if (!dtest[locate]) {
|
902
|
-
zp = z[i][j];
|
903
|
-
if (zp > z0)
|
904
|
-
iGT = i, jGT = j;
|
905
|
-
else
|
906
|
-
iLE = i, jLE = j;
|
907
|
-
continue;
|
908
|
-
}
|
909
|
-
vx = (x[iGT] + x[i]) * 0.5;
|
910
|
-
vy = (y[jGT] + y[j]) * 0.5;
|
911
|
-
locate = 3 * (jGT - j) + iGT - i + 4;
|
912
|
-
// Fourth point in rectangular boundary
|
913
|
-
ii = i + i_test[locate];
|
914
|
-
jj = j + j_test[locate];
|
915
|
-
bool legit_diag =
|
916
|
-
(legit == NULL || (legit[iLE][jLE] != 0.0
|
917
|
-
&& legit[iGT][jGT] != 0.0
|
918
|
-
&& legit[i][j] != 0.0
|
919
|
-
&& legit[ii][jj] != 0.0)) ? true : false;
|
920
|
-
zcentre = 0.25 * (z[iLE][jLE] + z[iGT][jGT] + z[i][j] + z[ii][jj]);
|
921
|
-
|
922
|
-
if (zcentre <= z0) {
|
923
|
-
append_segment(x[iGT], y[jGT], z[iGT][jGT], (legit == NULL)? 1.0: legit[iGT][jGT],
|
924
|
-
vx, vy, zcentre, legit_diag,
|
925
|
-
z0, ierr);
|
926
|
-
if (*ierr != 0) return false;
|
927
|
-
if (z[ii][jj] <= z0) {
|
928
|
-
iLE = ii, jLE = jj;
|
929
|
-
continue;
|
930
|
-
}
|
931
|
-
append_segment(x[ii], y[jj], z[ii][jj], (legit == NULL)? 1.0: legit[ii][jj],
|
932
|
-
vx, vy, zcentre, legit_diag,
|
933
|
-
z0, ierr);
|
934
|
-
if (*ierr != 0) return false;
|
935
|
-
if (z[i][j] <= z0) {
|
936
|
-
iGT = ii, jGT = jj;
|
937
|
-
iLE = i, jLE = j;
|
938
|
-
continue;
|
939
|
-
}
|
940
|
-
append_segment(x[i], y[j], z[i][j], (legit == NULL)? 1.0: legit[i][j],
|
941
|
-
vx, vy, zcentre, legit_diag,
|
942
|
-
z0, ierr);
|
943
|
-
if (*ierr != 0) return false;
|
944
|
-
iGT = i, jGT = j;
|
945
|
-
continue;
|
946
|
-
}
|
947
|
-
append_segment(vx, vy, zcentre, legit_diag,
|
948
|
-
x[iLE], y[jLE], z[iLE][jLE], (legit == NULL)? 1.0: legit[iLE][jLE],
|
949
|
-
z0, ierr);
|
950
|
-
if (*ierr != 0) return false;
|
951
|
-
if (z[i][j] > z0) {
|
952
|
-
iGT = i, jGT = j;
|
953
|
-
continue;
|
954
|
-
}
|
955
|
-
append_segment(vx, vy, zcentre, legit_diag,
|
956
|
-
x[i], y[j], z[i][j], (legit == NULL)? 1.0: legit[i][j],
|
957
|
-
z0, ierr);
|
958
|
-
if (*ierr != 0) return false;
|
959
|
-
if (z[ii][jj] <= z0) {
|
960
|
-
append_segment(vx, vy, zcentre, legit_diag,
|
961
|
-
x[ii], y[jj], z[ii][jj], (legit == NULL)? 1.0: legit[ii][jj],
|
962
|
-
z0, ierr);
|
963
|
-
if (*ierr != 0) return false;
|
964
|
-
iLE = ii;
|
965
|
-
jLE = jj;
|
966
|
-
continue;
|
967
|
-
}
|
968
|
-
iLE = i;
|
969
|
-
jLE = j;
|
970
|
-
iGT = ii;
|
971
|
-
jGT = jj;
|
972
|
-
}
|
973
|
-
}
|
974
|
-
|
975
|
-
// append_segment() -- append a line segment on the contour
|
976
|
-
static double xplot_last, yplot_last;
|
977
|
-
static int
|
978
|
-
append_segment(double xr, double yr, double zr, double OKr,
|
979
|
-
double xs, double ys, double zs, double OKs,
|
980
|
-
double z0, int *ierr)
|
981
|
-
{
|
982
|
-
if (zr == zs) { RAISE_ERROR("Contouring problem: zr = zs, which is illegal", ierr); return 0; }
|
983
|
-
double frac = (zr - z0) / (zr - zs);
|
984
|
-
if (frac < 0.0) { RAISE_ERROR("Contouring problem: frac < 0", ierr); return 0; }
|
985
|
-
if (frac > 1.0) { RAISE_ERROR("Contouring problem: frac > 1", ierr); return 0; }
|
986
|
-
double xplot = xr - frac * (xr - xs);
|
987
|
-
double yplot = yr - frac * (yr - ys);
|
988
|
-
// Avoid replot, which I suppose must be possible, given this code
|
989
|
-
if (num_in_curve > 0 && xplot == xplot_last && yplot == yplot_last)
|
990
|
-
return 1;
|
991
|
-
if (num_in_curve > max_in_curve - 1) {
|
992
|
-
// Get new storage if running on empty. Better to
|
993
|
-
// do this with an STL vector class
|
994
|
-
max_in_curve *= 2;
|
995
|
-
int i;
|
996
|
-
double *tmp = ALLOC_N_double(num_in_curve);
|
997
|
-
for (i = 0; i < num_in_curve; i++) tmp[i] = xcurve[i];
|
998
|
-
free(xcurve); xcurve = ALLOC_N_double(max_in_curve);
|
999
|
-
for (i = 0; i < num_in_curve; i++) xcurve[i] = tmp[i];
|
1000
|
-
for (i = 0; i < num_in_curve; i++) tmp[i] = ycurve[i];
|
1001
|
-
free(ycurve); ycurve = ALLOC_N_double(max_in_curve);
|
1002
|
-
for (i = 0; i < num_in_curve; i++) ycurve[i] = tmp[i];
|
1003
|
-
free(tmp);
|
1004
|
-
bool *tmpl = ALLOC_N_bool(num_in_curve);
|
1005
|
-
for (i = 0; i < num_in_curve; i++) tmpl[i] = legitcurve[i];
|
1006
|
-
free(legitcurve); legitcurve = ALLOC_N_bool(max_in_curve);
|
1007
|
-
for (i = 0; i < num_in_curve; i++) legitcurve[i] = tmpl[i];
|
1008
|
-
free(tmpl);
|
1009
|
-
}
|
1010
|
-
// A segment is appended only if both the present point and the last
|
1011
|
-
// point came by interpolating between OK points.
|
1012
|
-
xcurve[num_in_curve] = xplot;
|
1013
|
-
ycurve[num_in_curve] = yplot;
|
1014
|
-
if (OKr != 0.0 && OKs != 0.0)
|
1015
|
-
legitcurve[num_in_curve] = true;
|
1016
|
-
else
|
1017
|
-
legitcurve[num_in_curve] = false;
|
1018
|
-
num_in_curve++;
|
1019
|
-
xplot_last = xplot;
|
1020
|
-
yplot_last = yplot;
|
1021
|
-
return 1;
|
1022
|
-
}
|
1023
|
-
|
1024
|
-
|
1025
|
-
// Draw contour stored in (xcurve[],ycurve[],legitcurve[]), possibly with
|
1026
|
-
// labels (depending on global Label_contours).
|
1027
|
-
//
|
1028
|
-
#define FACTOR 3.0 // contour must be FACTOR*len long to be labelled
|
1029
|
-
static void
|
1030
|
-
draw_the_contour(
|
1031
|
-
long *dest_len_ptr,
|
1032
|
-
double **dest_xs_ptr,
|
1033
|
-
double **dest_ys_ptr,
|
1034
|
-
long *dest_sz_ptr,
|
1035
|
-
OBJ_PTR gaps,
|
1036
|
-
int *ierr)
|
1037
|
-
{
|
1038
|
-
if (num_in_curve == 1) {
|
1039
|
-
num_in_curve = 0;
|
1040
|
-
return;
|
1041
|
-
}
|
1042
|
-
int i, k;
|
1043
|
-
for (i = 0, k = 0; i < num_in_curve; i++) {
|
1044
|
-
if (legitcurve[i] == true) {
|
1045
|
-
// PUSH_POINT does num_in_path++
|
1046
|
-
PUSH_POINT(xcurve[i],ycurve[i]); num_in_path++;
|
1047
|
-
} else {
|
1048
|
-
if (num_in_path > 0 && num_in_path != k) {
|
1049
|
-
Array_Push(gaps, Integer_New(num_in_path), ierr);
|
1050
|
-
if (*ierr != 0) return;
|
1051
|
-
}
|
1052
|
-
k = num_in_path;
|
1053
|
-
}
|
1054
|
-
}
|
1055
|
-
Array_Push(gaps, Integer_New(num_in_path), ierr);
|
1056
|
-
num_in_curve = 0;
|
1057
|
-
}
|
1058
|
-
|
1059
|
-
// FLAG() -- check flag for gr_contour() and trace_contour()
|
1060
|
-
// ni = row (or, if ind==-1, number of rows)
|
1061
|
-
// nj = col (or, if ind==-1, number of cols)
|
1062
|
-
// if (ind == -1), get flag storage space; initialize flags to 0
|
1063
|
-
// if (ind == 1), check flag and then set it
|
1064
|
-
// if (ind == 2), clear the flag storage space
|
1065
|
-
// if (ind == 0), check flag, return value
|
1066
|
-
// RETURN value: Normally, the flag value (0 or 1). If the storage is
|
1067
|
-
// exhausted, return a number <0.
|
1068
|
-
#define NBITS 32
|
1069
|
-
static int
|
1070
|
-
FLAG(int ni, int nj, int ind, int *ierr)
|
1071
|
-
{
|
1072
|
-
static bool flag_storage_exists = false;
|
1073
|
-
static unsigned long *flag, mask[NBITS];
|
1074
|
-
static int size;
|
1075
|
-
static int ni_max; // x-dimension is saved
|
1076
|
-
int i, ipos, iword, ibit, return_value;
|
1077
|
-
switch (ind) {
|
1078
|
-
case -1:
|
1079
|
-
// Allocate storage for flag array
|
1080
|
-
if (flag_storage_exists) {
|
1081
|
-
RAISE_ERROR("storage is messed up (internal error)", ierr); return 0; }
|
1082
|
-
size = 1 + ni * nj / NBITS; // total storage array length
|
1083
|
-
flag = ALLOC_N_unsigned_long(size);
|
1084
|
-
// Create mask
|
1085
|
-
mask[0] = 1;
|
1086
|
-
for (i = 1; i < NBITS; i++)
|
1087
|
-
mask[i] = 2 * mask[i - 1];
|
1088
|
-
for (i = 0; i < size; i++) // Zero out flag
|
1089
|
-
flag[i] = 0;
|
1090
|
-
ni_max = ni; // Save for later
|
1091
|
-
flag_storage_exists = true;
|
1092
|
-
return 0;
|
1093
|
-
case 2:
|
1094
|
-
if (!flag_storage_exists) {
|
1095
|
-
RAISE_ERROR("No flag storage exists", ierr); return 0; }
|
1096
|
-
free(flag);
|
1097
|
-
flag_storage_exists = false;
|
1098
|
-
return 0;
|
1099
|
-
default:
|
1100
|
-
if (!flag_storage_exists) {
|
1101
|
-
RAISE_ERROR("No flag storage exists", ierr); return 0; }
|
1102
|
-
break;
|
1103
|
-
}
|
1104
|
-
// ind was not -1 or 2
|
1105
|
-
// Find location of bit.
|
1106
|
-
ipos = nj * ni_max + ni;
|
1107
|
-
iword = ipos / NBITS;
|
1108
|
-
ibit = ipos - iword * NBITS;
|
1109
|
-
// Check for something being broken here, causing to run out of space.
|
1110
|
-
// This should never happen, but may as well check.
|
1111
|
-
if (iword >= size)
|
1112
|
-
return (-99); // no space
|
1113
|
-
// Get flag.
|
1114
|
-
return_value = (0 != (*(flag + iword) & mask[ibit]));
|
1115
|
-
// If ind=1 and flag wasn't set, set the flag
|
1116
|
-
if (ind == 1 && !return_value)
|
1117
|
-
flag[iword] |= mask[ibit];
|
1118
|
-
// Return the flag value
|
1119
|
-
return return_value;
|
1120
|
-
}
|
1121
|
-
#undef NBITS
|
1122
|
-
|
1123
|
-
// end of contour code from Gri
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
static void c_make_contour(FM *p,
|
1128
|
-
long *dest_len_ptr,
|
1129
|
-
double **dest_xs_ptr,
|
1130
|
-
double **dest_ys_ptr,
|
1131
|
-
long *dest_sz_ptr,
|
1132
|
-
OBJ_PTR gaps,
|
1133
|
-
OBJ_PTR xs, OBJ_PTR ys,
|
1134
|
-
OBJ_PTR zs_data, double z_level,
|
1135
|
-
OBJ_PTR legit_data, int use_conrec, int *ierr) {
|
1136
|
-
|
1137
|
-
long xlen, ylen, num_zcolumns, num_zrows, num_columns, num_rows;
|
1138
|
-
double *x_coords = Vector_Data_for_Read(xs, &xlen, ierr);
|
1139
|
-
if (*ierr != 0) return;
|
1140
|
-
double *y_coords = Vector_Data_for_Read(ys, &ylen, ierr);
|
1141
|
-
if (*ierr != 0) return;
|
1142
|
-
double **zs = Table_Data_for_Read(zs_data, &num_zcolumns, &num_zrows, ierr);
|
1143
|
-
if (*ierr != 0) return;
|
1144
|
-
double **legit = Table_Data_for_Read(legit_data, &num_columns, &num_rows, ierr);
|
1145
|
-
if (*ierr != 0) return;
|
1146
|
-
double x_limit, y_limit;
|
1147
|
-
|
1148
|
-
if (x_coords == NULL || gaps == OBJ_NIL || zs == NULL || y_coords == NULL) {
|
1149
|
-
RAISE_ERROR("Sorry: bad args for make_contour. Need to provide xs, ys, gaps, and zs.", ierr); return;
|
1150
|
-
}
|
1151
|
-
if (xlen != num_columns || ylen != num_rows) {
|
1152
|
-
RAISE_ERROR("Sorry: bad args for make_contour. Needs xs.size == num columns and ys.size == num rows.", ierr); return;
|
1153
|
-
}
|
1154
|
-
if (num_zcolumns != num_columns || num_zrows != num_rows) {
|
1155
|
-
RAISE_ERROR("Sorry: bad args for make_contour. Needs same dimension zs and legit flags.", ierr); return;
|
1156
|
-
}
|
1157
|
-
|
1158
|
-
// NOTE: contour data is TRANSPOSE of tioga data, so we switch x's and y's in the call
|
1159
|
-
|
1160
|
-
if (use_conrec == 1) {
|
1161
|
-
x_limit = 0.001*(x_coords[xlen-1] - x_coords[0])/xlen;
|
1162
|
-
if (x_limit < 0) x_limit = -x_limit;
|
1163
|
-
y_limit = 0.001*(y_coords[ylen-1] - y_coords[0])/ylen;
|
1164
|
-
if (y_limit < 0) y_limit = -y_limit;
|
1165
|
-
conrec(zs, 0, num_rows-1, 0, num_columns-1, y_coords, x_coords, 1, &z_level,
|
1166
|
-
dest_len_ptr, dest_ys_ptr, dest_xs_ptr, dest_sz_ptr, gaps, y_limit, x_limit, ierr);
|
1167
|
-
} else {
|
1168
|
-
gr_contour(y_coords, x_coords, zs, legit, num_rows, num_columns, z_level,
|
1169
|
-
dest_len_ptr, dest_ys_ptr, dest_xs_ptr, dest_sz_ptr, gaps, ierr);
|
1170
|
-
}
|
1171
|
-
}
|
1172
|
-
|
1173
|
-
|
1174
|
-
OBJ_PTR c_private_make_contour(OBJ_PTR fmkr, FM *p,
|
1175
|
-
OBJ_PTR gaps, // these vectors get the results
|
1176
|
-
OBJ_PTR xs, OBJ_PTR ys, // data x coordinates and y coordinates
|
1177
|
-
OBJ_PTR zs, double z_level, // the table of values and the desired contour level
|
1178
|
-
OBJ_PTR legit, // the table of flags (nonzero means okay)
|
1179
|
-
int method, // int == 1 means CONREC
|
1180
|
-
int *ierr
|
1181
|
-
) {
|
1182
|
-
/* uses Xvec_data and Yvec_data to create a cubic spline interpolant.
|
1183
|
-
once the spline interpolant is created, it is sampled at the n_pts_to_add in Xs.
|
1184
|
-
Xvec entry i is set to the value of the spline at Yvec entry i.
|
1185
|
-
Both the X_data and the Xs should be stored in ascending order.
|
1186
|
-
There is a boundary condition choice to be made for each end concerning the slope.
|
1187
|
-
If clamped is true, the corresponding slope argument value sets the slope.
|
1188
|
-
If clamped is false (known as a "free" or "natural" spline),
|
1189
|
-
the 2nd derivative is set to 0 and the slope is determined by the fit.
|
1190
|
-
In this case, the corresponding slope argument is ignored.
|
1191
|
-
*/
|
1192
|
-
long dest_len, dest_sz;
|
1193
|
-
double *dest_xs_data;
|
1194
|
-
double *dest_ys_data;
|
1195
|
-
OBJ_PTR Xvec;
|
1196
|
-
OBJ_PTR Yvec;
|
1197
|
-
OBJ_PTR pts_array;
|
1198
|
-
|
1199
|
-
dest_len = 0; dest_sz = 3000;
|
1200
|
-
dest_xs_data = ALLOC_N_double(dest_sz);
|
1201
|
-
dest_ys_data = ALLOC_N_double(dest_sz);
|
1202
|
-
|
1203
|
-
c_make_contour(p, &dest_len, &dest_xs_data, &dest_ys_data, &dest_sz,
|
1204
|
-
gaps, xs, ys, zs, z_level, legit, method, ierr);
|
1205
|
-
if (*ierr != 0) RETURN_NIL;
|
1206
|
-
|
1207
|
-
Xvec = Vector_New(dest_len, dest_xs_data);
|
1208
|
-
Yvec = Vector_New(dest_len, dest_ys_data);
|
1209
|
-
free(dest_xs_data);
|
1210
|
-
free(dest_ys_data);
|
1211
|
-
|
1212
|
-
pts_array = Array_New(2);
|
1213
|
-
Array_Store(pts_array,0,Xvec,ierr);
|
1214
|
-
if (*ierr != 0) RETURN_NIL;
|
1215
|
-
Array_Store(pts_array,1,Yvec,ierr);
|
1216
|
-
if (*ierr != 0) RETURN_NIL;
|
1217
|
-
return pts_array;
|
1218
|
-
}
|
1219
|
-
|
1220
|
-
|