home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
graphic
/
csg_rt
/
sil.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-28
|
5KB
|
195 lines
/*
SIL.C Simple intersection lists
*/
/*...sincludes:0:*/
#include <stdlib.h>
#include <stddef.h>
#include <memory.h>
#include <math.h>
#include "standard.h"
#include "rt.h"
#include "vector.h"
#define _SIL_
#include "sil.h"
/*...vrt\46\h:0:*/
/*...vvector\46\h:0:*/
/*...vsil\46\h:0:*/
/*...e*/
#define ZERO(x) ( ((x)>=-1.0e-100) && ((x)<=1.0e-100) )
/*...st_a_bit_later:0:*/
static double t_a_bit_later(double t)
{
return ( t + 100.0 );
}
/*...e*/
/*...st_a_bit_before:0:*/
static double t_a_bit_before(double t)
{
return ( t - 100.0 );
}
/*...e*/
/*...sintersect_linear_t:0:*/
void intersect_linear_t(
double coeff_of_t, double constant_term,
VECTOR p, VECTOR q,
void *shapeinfo, double (*value_of_shape)(void *shapeinfo, VECTOR v),
SIL *sil
)
{
if ( ZERO(coeff_of_t) )
/* No intersection with solid surface */
{
if ( (*value_of_shape)(shapeinfo, p) <= 0.0 )
/* Completely in solid */
{
sil -> n_sis = 2;
sil -> sis [0].t = -INFINITE;
sil -> sis [0].entering = TRUE;
sil -> sis [1].t = INFINITE;
sil -> sis [1].entering = FALSE;
}
else
/* Completely out of solid */
sil -> n_sis = 0;
}
else
/* Intersects solid exactly once */
{
double t = - constant_term / coeff_of_t;
sil -> n_sis = 2;
sil -> sis [0].entering = TRUE;
sil -> sis [1].entering = FALSE;
if ( (*value_of_shape)(shapeinfo, t_along_pq(p, q, t_a_bit_later(t))) <= 0.0 )
/* Entering solid */
{
sil -> sis [0].t = t;
sil -> sis [1].t = INFINITE;
}
else
/* Leaving solid */
{
sil -> sis [0].t = -INFINITE;
sil -> sis [1].t = t;
}
}
}
/*...e*/
/*...sintersect_quadratic_t:0:*/
void intersect_quadratic_t(
double qa, double qb, double qc,
VECTOR p, VECTOR q,
void *shapeinfo, double (*value_of_shape)(void *shapeinfo, VECTOR v),
SIL *sil
)
{
double qs;
if ( ZERO(qa) )
/*...sdo linear case:16:*/
intersect_linear_t(qb, qc, p, q, shapeinfo, value_of_shape, sil);
/*...e*/
else if ( (qs = qb*qb - 4.0*qa*qc) < 0.0 )
/*...sno real roots:16:*/
/* No real roots => no intersections, all solid or all empty */
{
if ( (*value_of_shape)(shapeinfo, p) <= 0.0 )
{
sil -> n_sis = 2;
sil -> sis [0].t = -INFINITE;
sil -> sis [0].entering = TRUE;
sil -> sis [1].t = INFINITE;
sil -> sis [1].entering = FALSE;
}
else
sil -> n_sis = 0;
}
/*...e*/
else if ( ZERO(qs) )
/*...sone double root:16:*/
{
double t = -qb / (qa + qa);
BOOLEAN from_inside = ( (*value_of_shape)(shapeinfo, t_along_pq(p, q, t_a_bit_before(t))) <= 0.0 );
BOOLEAN to_inside = ( (*value_of_shape)(shapeinfo, t_along_pq(p, q, t_a_bit_later(t))) <= 0.0 );
#define DUAL_SWITCH(f,t) (((f)<<1)+(t))
switch ( DUAL_SWITCH(from_inside, to_inside) )
{
case DUAL_SWITCH(FALSE, FALSE): /* Grazing surface */
sil -> n_sis = 0;
break;
case DUAL_SWITCH(FALSE, TRUE): /* Entering solid area */
sil -> n_sis = 2;
sil -> sis [0].t = t;
sil -> sis [0].entering = TRUE;
sil -> sis [1].t = INFINITE;
sil -> sis [1].entering = FALSE;
break;
case DUAL_SWITCH( TRUE, FALSE): /* Leaving solid area */
sil -> n_sis = 2;
sil -> sis [0].t = -INFINITE;
sil -> sis [0].entering = TRUE;
sil -> sis [1].t = t;
sil -> sis [1].entering = FALSE;
break;
case DUAL_SWITCH( TRUE, TRUE): /* Never left solid area */
sil -> n_sis = 2;
sil -> sis [0].t = -INFINITE;
sil -> sis [0].entering = TRUE;
sil -> sis [1].t = INFINITE;
sil -> sis [1].entering = FALSE;
break;
}
}
/*...e*/
else
/*...stwo roots:16:*/
{
double rooted = sqrt(qs);
double t1 = (-qb - rooted) / (qa + qa);
double t2 = (-qb + rooted) / (qa + qa);
if ( t1 > t2 )
/* Ensure t1 is lower than t2 */
{
double t = t1;
t1 = t2;
t2 = t;
}
if ( (*value_of_shape)(shapeinfo, t_along_pq(p, q, (t1 + t2) * 0.5)) <= 0.0 )
/* Middle part is the solid part */
{
sil -> n_sis = 2;
sil -> sis [0].t = t1;
sil -> sis [0].entering = TRUE;
sil -> sis [1].t = t2;
sil -> sis [1].entering = FALSE;
}
else
/* Regions before and after middle part are the solid parts */
{
sil -> n_sis = 4;
sil -> sis [0].t = -INFINITE;
sil -> sis [0].entering = TRUE;
sil -> sis [1].t = t1;
sil -> sis [1].entering = FALSE;
sil -> sis [2].t = t2;
sil -> sis [2].entering = TRUE;
sil -> sis [3].t = INFINITE;
sil -> sis [3].entering = FALSE;
}
}
/*...e*/
}
/*...e*/