ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/cone.c
Revision: 1.3
Committed: Sat Jan 19 13:43:28 1991 UTC (33 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.2: +4 -2 lines
Log Message:
changed error checking to allow for slightly negative radii

File Contents

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