1 /*
2  * Copyright (C) 1997-2005, R3vis Corporation.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17  * USA, or visit http://www.gnu.org/copyleft/lgpl.html.
18  *
19  * Original Contributor:
20  *   Wes Bethel, R3vis Corporation, Marin County, California
21  * Additional Contributor(s):
22  *
23  * The OpenRM project is located at http://openrm.sourceforge.net/.
24  */
25 /*
26  * $Id: rmverrplot.c,v 1.5 2005/02/19 16:09:13 wes Exp $
27  * Version: $Name: OpenRM-1-6-0-2-RC2 $
28  * $Revision: 1.5 $
29  * $Log: rmverrplot.c,v $
30  * Revision 1.5  2005/02/19 16:09:13  wes
31  * Distro sync and consolidation.
32  *
33  * Revision 1.4  2005/01/23 17:11:02  wes
34  * Copyright updated to 2005.
35  *
36  * Revision 1.3  2004/01/17 04:09:26  wes
37  * Updated copyright line for 2004.
38  *
39  * Revision 1.2  2003/02/02 02:07:23  wes
40  * Updated copyright to 2003.
41  *
42  * Revision 1.1.1.1  2003/01/28 02:15:23  wes
43  * Manual rebuild of rm150 repository.
44  *
45  * Revision 1.6  2003/01/16 22:21:20  wes
46  * Updated all source files to reflect new organization of header files:
47  * all header files formerly located in include/rmaux, include/rmi, include/rmv
48  * are now located in include/rm.
49  *
50  * Revision 1.5  2002/04/30 19:40:00  wes
51  * Updated copyright dates.
52  *
53  * Revision 1.4  2001/03/31 17:10:08  wes
54  * v1.4.0-alpha-2 checkin.
55  *
56  * Revision 1.3  2000/08/28 01:34:30  wes
57  * No signficant changes.
58  *
59  * Revision 1.2  2000/04/20 16:17:45  wes
60  * JDB modifications: code rearrangement, additional docs.
61  *
62  * Revision 1.1  2000/04/17 00:05:23  wes
63  * Lots of documentation updates, courtesy of jdb.
64  *
65  * Revision 1.1.1.1  2000/02/28 21:29:40  wes
66  * OpenRM 1.2 Checkin
67  *
68  * Revision 1.1.1.1  2000/02/28 17:18:48  wes
69  * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
70  *
71  */
72 
73 #include <rm/rm.h>
74 #include <rm/rmv.h>
75 #include "rmvprivt.h"
76 
77 /*
78  * ----------------------------------------------------
79  * @Name rmvI2ErrorPlot
80  @pstart
81  RMenum rmvI2ErrorPlot (RMvertex2D (*appgridfunc)(int i),
82                         float (*appu1func)(int i),
83 			float (*appu2func)(int i),
84 			float (*appl1func)(int i),
85 			float (*appl2func)(int i),
86 			float (*appdata2func)(int i),
87 			RMvisMap *vmap,
88 			int axis_offset_flag,
89 			int npts,
90 			RMenum linewidth,
91 			RMenum linestyle,
92 			RMnode *n)
93  @pend
94 
95  @astart
96 
97  RMvertex2D (*appgridfunc)(int i) - a handle to a caller-supplied
98     function that returns an RMvertex2D (x, y) corresponding to the
99     grid point (i) (input).
100 
101  float (*appu1func)(int i) - a handle to caller-supplied function that
102     returns a lower bound float for the upper pair at the grid point
103     (i) (input).
104 
105  float (*appu2func)(int i) - a handle to caller-supplied function that
106     returns a upper bound float for the upper pair at the grid point
107     (i) (input).
108 
109  float (*appl1func)(int i) - a handle to caller-supplied function that
110     returns a lower bound float for the lower pair at the grid point
111     (i) (input).
112 
113  float (*appl2func)(int i) - a handle to caller-supplied function that
114     returns a upper bound float for the lower pair at the grid point
115     (i) (input).
116 
117  float (*appdata2func)(int i) - a handle to a caller-supplied function
118     that returns a scalar value for the grid point (i).  This value is
119     used in conjunction with the RMvismap to compute vertex color.
120 
121  RMvisMap *vmap - a handle to an RMvisMap object (input).
122 
123  int axis_offset_flag - an RMenum specifying in which axis to
124     offset the glyph.  Must be one of RMV_XAXIS_OFFSET,
125     RMV_YAXIS_OFFSET (input).
126 
127  int npts - int specifying number of grid data points (input).
128 
129  RMenum linewidth_enum - an RMenum specifying the line width.  Must be
130     one of RM_LINEWIDTH_NARROW, RM_LINEWIDTH_MEDIUM,
131     RM_LINEWIDTH_HEAVY, or RM_LINEWIDTH_[1..8] (input).
132 
133  RMenum linestyle_enum - an RMenum specifying the lline style.  Must
134     be one of RM_LINES_SOLID, RM_LINES_DASHED, RM_LINES_DOTTED,
135     RM_LINES_DOT_DASH, or RM_LINES_DASH_DASH_DOT (input).
136 
137  RMnode *n - a handle to an RMnode (modified).
138  @aend
139 
140  @dstart
141 
142  Creates an "error bar" plot for indicating data ranges.  Pairs of
143  error bars are plotted from the four caller-supplied functions, {u1,
144  u2, l1, l2}.  These functions return a data value for a given grid
145  point and indicate a pair of data ranges {[l1..l2], [u1..u2]}.  The
146  secondary data function can be used with the RMvisMap to color the
147  error bars.
148 
149  Upon success, RM_CHILL is returned to the caller and the error plot
150  geometry has been added to the RMnode.  Otherwise, RM_WHACKED is
151  returned.
152 
153  @dend
154  * ----------------------------------------------------
155  */
156 RMenum
rmvI2ErrorPlot(RMvertex2D (* appgridfunc)(int i),float (* appu1func)(int i),float (* appu2func)(int i),float (* appl1func)(int i),float (* appl2func)(int i),float (* appdata2func)(int i),RMvisMap * vmap,int axis_offset_flag,int npts,RMenum linewidth,RMenum linestyle,RMnode * n)157 rmvI2ErrorPlot (RMvertex2D (*appgridfunc)(int i),
158 	        float (*appu1func)(int i),
159 	        float (*appu2func)(int i),
160 	        float (*appl1func)(int i),
161 	        float (*appl2func)(int i),
162 	        float (*appdata2func)(int i),
163 	        RMvisMap *vmap,
164 	        int axis_offset_flag,
165 	        int npts,
166 	        RMenum linewidth,
167 	        RMenum linestyle,
168 	        RMnode *n)
169 {
170     int          i, j = 0;
171     RMprimitive *t;
172     RMvertex2D  *v;
173     RMcolor4D   *c;
174 
175     /* error check on functions, etc. */
176     {
177 	int s1, s2, s3, s4, s5, s6, s7;
178 
179 	s1 = RM_ASSERT((void *)n, "rmvI2ErrorPlot error: NULL RMnode for return parameter");
180 	s2 = RM_ASSERT((void *)appgridfunc, "rmvI2ErrorPlot error: NULL app grid callback");
181 	s3 = RM_ASSERT((void *)appu1func, "rmvI2ErrorPlot error: NULL app u1 callback ");
182 	s4 = RM_ASSERT((void *)appu2func, "rmvI2ErrorPlot error: NULL app u2 callback ");
183 	s5 = RM_ASSERT((void *)appl1func, "rmvI2ErrorPlot error: NULL app l1 callback ");
184 	s6 = RM_ASSERT((void *)appl2func, "rmvI2ErrorPlot error: NULL app l2 callback ");
185 	s7 = RM_CHILL;
186 	if (!(((vmap != NULL) && (appdata2func != NULL)) || ((vmap == NULL) && (appdata2func == NULL))))
187 	    s7 = RM_ASSERT((void *)NULL,"rmvI2ErrorPlot error: the vismap and secondary data callback function must BOTH be NULL or defined.");
188 
189 	if ((s1 == RM_WHACKED) || (s2 == RM_WHACKED) || (s3 == RM_WHACKED) || (s4 == RM_WHACKED) || (s5 == RM_WHACKED) || (s6 == RM_WHACKED) || (s7 == RM_WHACKED))
190 	    return(RM_WHACKED);
191     }
192 
193     v = rmVertex2DNew(npts * 4);
194     t = rmPrimitiveNew(RM_LINES);
195 
196     if (vmap != NULL)
197         c = rmColor4DNew(npts * 2);
198     else
199 	c = NULL;
200 
201     /* do the upper part */
202     for (i = 0; i < npts; i++)
203     {
204 	float      maxs, uppers;
205 	RMvertex2D base;
206 
207 	base = (*appgridfunc)(i);
208 	maxs = (*appu1func)(i);
209 	uppers = (*appu2func)(i);
210 
211 	v[j] = base;
212 	v[j + 1] = base;
213 
214 	switch (axis_offset_flag)
215 	   {
216 	   case RMV_XAXIS_OFFSET:
217 	      v[j].x += uppers;
218 	      v[j + 1].x += maxs;
219 	      break;
220 
221 	   case RMV_YAXIS_OFFSET:
222 	      v[j].y += uppers;
223 	      v[j + 1].y += maxs;
224 	      break;
225 
226 	   default: /* bogus axis offset enum */
227 	      break;
228 	   }
229 
230 	j += 2;
231 
232 	if (c)
233 	{
234 	    int   k;
235 	    float d2;
236 
237 	    d2 = (*appdata2func)(i);
238 	    k = rmVismapIndexFromData(vmap, d2);
239 	    rmVismapGetColor4D(vmap, k, (c + i));
240 	}
241     }
242 
243     /* do the lower part */
244     for (i = 0; i < npts; i++)
245     {
246 	float      mins, lowers;
247 	RMvertex2D base;
248 
249 	base = (*appgridfunc)(i);
250 	mins = (*appl1func)(i);
251 	lowers = (*appl2func)(i);
252 
253 	v[j] = base;
254 	v[j + 1] = base;
255 
256 	switch (axis_offset_flag)
257 	   {
258 	   case RMV_XAXIS_OFFSET:
259 	      v[j].x += lowers;
260 	      v[j + 1].x += mins;
261 	      break;
262 
263 	   case RMV_YAXIS_OFFSET:
264 	      v[j].y += lowers;
265 	      v[j + 1].y += mins;
266 	      break;
267 
268 	   default: /* bogus axis offset enum */
269 	      break;
270 	   }
271 
272 	if (c)
273 	{
274 	    int   k;
275 	    float d2;
276 
277 	    d2 = (*appdata2func)(i);
278 	    k = rmVismapIndexFromData(vmap, d2);
279 	    rmVismapGetColor4D(vmap, k, (c + i + npts));
280 	}
281 	j += 2;
282     }
283     rmPrimitiveSetVertex2D(t, (npts * 4), v, RM_COPY_DATA, NULL);
284 
285     if (c)
286     {
287         rmPrimitiveSetColor4D(t, (npts * 2), c, RM_COPY_DATA, NULL);
288 	rmColor4DDelete(c);
289     }
290     rmNodeSetLineWidth(n, linewidth);
291     rmNodeSetLineStyle(n, linestyle);
292 
293     /* now, add the new primitive onto the node */
294     rmNodeAddPrimitive(n, t);
295     rmVertex2DDelete(v);
296 
297     return(RM_CHILL);
298 }
299 /* EOF */
300