1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8 /*
9 * $Header: /src/master/dx/src/exec/dxmods/rotate.c,v 1.3 1999/05/10 15:45:30 gda Exp $
10 */
11
12 #include <dxconfig.h>
13
14
15 #include <dx/dx.h>
16 #include <ctype.h>
17
18 static int getdim(Object dimo, int *dim);
19 static int getmatrix(int dim, float deg, Matrix *m);
20
21 /* should the default rotation be 90? */
22 #define DEF_AXIS 1
23 #define DEF_DEG 0.0
24
25 #define MAXINPUTS 45 /* obj + 2 inputs w/defaults + 2 w/o + 20 repeat pairs */
26
27 int
m_Rotate(Object * in,Object * out)28 m_Rotate(Object *in, Object *out)
29 {
30 float deg = DEF_DEG;
31 int i, dim = DEF_AXIS;
32 int seen_null = 0;
33 int say_warn = 0;
34 Object xformed = NULL;
35 Matrix m;
36
37 out[0] = NULL;
38
39 if (!in[0]) {
40 DXSetError(ERROR_BAD_PARAMETER, "#10000", "input");
41 return ERROR;
42 }
43
44 i = 1;
45
46 /* handle the first 2 parameters because they have default values.
47 */
48 if (!in[1] || !in[2]) {
49
50 if (in[1] && !getdim(in[1], &dim))
51 return ERROR;
52
53 if (in[2] && !DXExtractFloat(in[2], °)) {
54 DXSetError(ERROR_BAD_PARAMETER, "#10080", "rotation");
55 return ERROR;
56 }
57
58 if (!getmatrix(dim, deg, &m))
59 return ERROR;
60
61 xformed = (Object)DXNewXform(in[0], m);
62 if (!xformed)
63 return ERROR;
64
65 /* start at 3rd parm */
66 i = 3;
67 }
68
69
70 /* parse rest of parms in pairs: axis letter, number of degrees
71 * if either of the first two parms was null, this loop starts at 3.
72 * otherwise it starts at 1.
73 */
74 for ( ; i<MAXINPUTS; i+=2) {
75
76 /* allow a pair of nulls, but if one is non-null, make sure it
77 * has a matching parameter.
78 */
79 if (!in[i] && in[i+1]) {
80 DXSetError(ERROR_BAD_PARAMETER, "#10000", "axis");
81 goto error;
82 }
83
84 if (in[i] && !in[i+1]) {
85 DXSetError(ERROR_BAD_PARAMETER, "#10000", "rotation");
86 goto error;
87 }
88
89 if (!in[i] && !in[i+1]) {
90 seen_null = 1;
91 continue;
92 }
93
94 if (seen_null) {
95 say_warn = 1;
96 seen_null = 0;
97 }
98
99 /* get axis and number of degrees of rotation.
100 */
101 if (!getdim(in[i], &dim))
102 goto error;
103
104 if (!DXExtractFloat(in[i+1], °)) {
105 DXSetError(ERROR_BAD_PARAMETER, "#10080", "rotation");
106 goto error;
107 }
108
109 /* turn axis & degrees into a transformation matrix
110 */
111 if (!getmatrix(dim, deg, &m))
112 goto error;
113
114 /* the following shuffling is done so that if there is an
115 * error, we can delete the partially rotated object.
116 * out[0] get zeroed so that if there is an error in a
117 * subsequent set of rotations, we can just call DXErrorReturn.
118 */
119 out[0] = (Object)DXNewXform((xformed ? xformed : in[0]), m);
120
121 if (!out[0])
122 goto error;
123
124 xformed = out[0];
125 out[0] = NULL;
126
127 }
128
129 if (say_warn)
130 DXWarning("skipping null objects in rotation list");
131
132 out[0] = xformed;
133 return(out[0] ? OK : ERROR);
134
135 error:
136 DXDelete(xformed);
137 out[0] = NULL;
138 return ERROR;
139
140 }
141
getdim(Object dimo,int * dim)142 static int getdim(Object dimo, int *dim)
143 {
144 char *ax;
145
146 /* if string given, convert to integer */
147 if (DXExtractString(dimo, &ax)) {
148
149 if (ax[1] != '\0')
150 goto error;
151
152 switch(ax[0]) {
153 case 'x':
154 case 'X': *dim = 0; break;
155 case 'y':
156 case 'Y': *dim = 1; break;
157 case 'z':
158 case 'Z': *dim = 2; break;
159 default:
160 goto error;
161
162 }
163
164 } else if (DXExtractInteger(dimo, dim)) {
165
166 if (*dim < 0 || *dim > 3)
167 goto error;
168
169 } else
170 goto error;
171
172
173 return OK;
174
175 error:
176 DXErrorReturn(ERROR_BAD_PARAMETER, "axis must be X, Y, Z or 0, 1, 2");
177
178 }
179
180
getmatrix(int dim,float deg,Matrix * m)181 static int getmatrix(int dim, float deg, Matrix *m)
182 {
183 /* set rotation matrix */
184 switch (dim) {
185 case 0:
186 *m = DXRotateX(deg * DEG);
187 break;
188 case 1:
189 *m = DXRotateY(deg * DEG);
190 break;
191 case 2:
192 *m = DXRotateZ(deg * DEG);
193 break;
194 default:
195 DXSetError(ERROR_BAD_PARAMETER, "axis must be X, Y, Z or 0, 1, 2");
196 return ERROR;
197 }
198
199 return OK;
200 }
201