ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/cone.c
Revision: 2.11
Committed: Fri Sep 16 15:09:21 2016 UTC (7 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad5R1, rad5R3, HEAD
Changes since 2.10: +4 -3 lines
Log Message:
Added checks for illegal cones/rings/cylinders

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: cone.c,v 2.10 2016/04/21 00:40:35 greg Exp $";
3 #endif
4 /*
5 * cone.c - routines for making cones
6 */
7
8 #include "copyright.h"
9
10 #include "standard.h"
11
12 #include "object.h"
13
14 #include "otypes.h"
15
16 #include "cone.h"
17
18 /*
19 * In general, a cone may be any one of a cone, a cylinder, a ring,
20 * a cup (inverted cone), or a tube (inverted cylinder).
21 * Most cones are specified with a starting point and radius and
22 * an ending point and radius. In the cases of a cylinder or tube,
23 * only one radius is needed. In the case of a ring, a normal direction
24 * is specified instead of a second endpoint.
25 *
26 * mtype (cone|cup) name
27 * 0
28 * 0
29 * 8 P0x P0y P0z P1x P1y P1z R0 R1
30 *
31 * mtype (cylinder|tube) name
32 * 0
33 * 0
34 * 7 P0x P0y P0z P1x P1y P1z R
35 *
36 * mtype ring name
37 * 0
38 * 0
39 * 8 Px Py Pz Nx Ny Nz R0 R1
40 */
41
42
43 CONE *
44 getcone( /* get cone structure */
45 OBJREC *o,
46 int getxf
47 )
48 {
49 int sgn0, sgn1;
50 CONE *co;
51
52 if ((co = (CONE *)o->os) == NULL) {
53
54 co = (CONE *)malloc(sizeof(CONE));
55 if (co == NULL)
56 error(SYSTEM, "out of memory in makecone");
57
58 co->ca = o->oargs.farg;
59 /* get radii */
60 if ((o->otype == OBJ_CYLINDER) | (o->otype == OBJ_TUBE)) {
61 if (o->oargs.nfargs != 7)
62 goto argcerr;
63 if (co->ca[6] < -FTINY) {
64 objerror(o, WARNING, "negative radius");
65 o->otype = o->otype == OBJ_CYLINDER ?
66 OBJ_TUBE : OBJ_CYLINDER;
67 co->ca[6] = -co->ca[6];
68 } else if (co->ca[6] <= FTINY)
69 goto raderr;
70 co->p0 = 0; co->p1 = 3;
71 co->r0 = co->r1 = 6;
72 } else {
73 if (o->oargs.nfargs != 8)
74 goto argcerr;
75 if (co->ca[6] < -FTINY) sgn0 = -1;
76 else if (co->ca[6] > FTINY) sgn0 = 1;
77 else sgn0 = 0;
78 if (co->ca[7] < -FTINY) sgn1 = -1;
79 else if (co->ca[7] > FTINY) sgn1 = 1;
80 else sgn1 = 0;
81 if (sgn0+sgn1 == 0)
82 goto raderr;
83 if ((sgn0 < 0) | (sgn1 < 0)) {
84 if (o->otype == OBJ_RING)
85 goto raderr;
86 objerror(o, WARNING, "negative radii");
87 o->otype = o->otype == OBJ_CONE ?
88 OBJ_CUP : OBJ_CONE;
89 }
90 co->ca[6] = co->ca[6]*sgn0;
91 co->ca[7] = co->ca[7]*sgn1;
92 if (co->ca[7] - co->ca[6] > FTINY) {
93 if (o->otype == OBJ_RING)
94 co->p0 = co->p1 = 0;
95 else {
96 co->p0 = 0; co->p1 = 3;
97 }
98 co->r0 = 6; co->r1 = 7;
99 } else if (co->ca[6] - co->ca[7] > FTINY) {
100 if (o->otype == OBJ_RING)
101 co->p0 = co->p1 = 0;
102 else {
103 co->p0 = 3; co->p1 = 0;
104 }
105 co->r0 = 7; co->r1 = 6;
106 } else {
107 if (o->otype == OBJ_RING)
108 goto raderr;
109 o->otype = o->otype == OBJ_CONE ?
110 OBJ_CYLINDER : OBJ_TUBE;
111 o->oargs.nfargs = 7;
112 co->p0 = 0; co->p1 = 3;
113 co->r0 = co->r1 = 6;
114 }
115 }
116 /* get axis orientation */
117 if (o->otype == OBJ_RING)
118 VCOPY(co->ad, o->oargs.farg+3);
119 else {
120 co->ad[0] = CO_P1(co)[0] - CO_P0(co)[0];
121 co->ad[1] = CO_P1(co)[1] - CO_P0(co)[1];
122 co->ad[2] = CO_P1(co)[2] - CO_P0(co)[2];
123 }
124 co->al = normalize(co->ad);
125 if (co->al == 0.0) {
126 objerror(o, WARNING, "unknown orientation");
127 free(co);
128 return(NULL);
129 }
130 /* compute axis and side lengths */
131 if (o->otype == OBJ_RING) {
132 co->al = 0.0;
133 co->sl = CO_R1(co) - CO_R0(co);
134 } else if ((o->otype == OBJ_CONE) | (o->otype == OBJ_CUP)) {
135 co->sl = co->ca[7] - co->ca[6];
136 co->sl = sqrt(co->sl*co->sl + co->al*co->al);
137 } else { /* OBJ_CYLINDER or OBJ_TUBE */
138 co->sl = co->al;
139 }
140 co->tm = NULL;
141 o->os = (char *)co;
142 }
143 if (getxf && co->tm == NULL)
144 conexform(co);
145 return(co);
146
147 argcerr:
148 objerror(o, USER, "bad # arguments");
149 raderr:
150 objerror(o, WARNING, "illegal radii");
151 free(co);
152 return(NULL);
153 }
154
155
156 void
157 freecone(OBJREC *o) /* free memory associated with cone */
158 {
159 CONE *co = (CONE *)o->os;
160
161 if (co == NULL)
162 return;
163 if (co->tm != NULL)
164 free((void *)co->tm);
165 free((void *)co);
166 o->os = NULL;
167 }
168
169
170 void
171 conexform(CONE *co) /* get cone transformation matrix */
172 {
173 MAT4 m4;
174 double d;
175 int i;
176
177 co->tm = (RREAL (*)[4])malloc(sizeof(MAT4));
178 if (co->tm == NULL)
179 error(SYSTEM, "out of memory in conexform");
180
181 /* translate to origin */
182 setident4(co->tm);
183 if (co->r0 == co->r1)
184 d = 0.0;
185 else
186 d = CO_R0(co) / (CO_R1(co) - CO_R0(co));
187 for (i = 0; i < 3; i++)
188 co->tm[3][i] = d*(CO_P1(co)[i] - CO_P0(co)[i])
189 - CO_P0(co)[i];
190
191 /* rotate to positive z-axis */
192 setident4(m4);
193 d = co->ad[1]*co->ad[1] + co->ad[2]*co->ad[2];
194 if (d <= FTINY*FTINY) {
195 m4[0][0] = 0.0;
196 m4[0][2] = co->ad[0];
197 m4[2][0] = -co->ad[0];
198 m4[2][2] = 0.0;
199 } else {
200 d = sqrt(d);
201 m4[0][0] = d;
202 m4[1][0] = -co->ad[0]*co->ad[1]/d;
203 m4[2][0] = -co->ad[0]*co->ad[2]/d;
204 m4[1][1] = co->ad[2]/d;
205 m4[2][1] = -co->ad[1]/d;
206 m4[0][2] = co->ad[0];
207 m4[1][2] = co->ad[1];
208 m4[2][2] = co->ad[2];
209 }
210 multmat4(co->tm, co->tm, m4);
211
212 /* scale z-axis */
213 if ((co->p0 != co->p1) & (co->r0 != co->r1)) {
214 setident4(m4);
215 m4[2][2] = (CO_R1(co) - CO_R0(co)) / co->al;
216 multmat4(co->tm, co->tm, m4);
217 }
218 }