home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Graphics
/
Graphics.zip
/
povsrc31.zip
/
rbezier.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-11-26
|
40KB
|
1,671 lines
/*
overit rychlost:
zda add_solution pocita spravne nejdrive ty s mensim orderem
*/
#include "frame.h"
#include "vector.h"
#include "povproto.h"
#include "bezier.h"
#include "matrices.h"
#include "objects.h"
#include "povray.h"
#include "bezier.h"
#include "rbezier.h"
#ifdef RBezierPatch
/* Yet another epsilon */
#define YAEP (1.0e-8)
#define MAGICAL_CONSTANT (1.0 - 0.2)
/*YS*/
#ifndef INFINITY
#define INFINITY (1.0e100)
#endif
/*YS*/
#define VERY_SMALL_EPSILON (1e-20)
/*YS*/
#ifndef MACOS
/* just for debugging */
#define FIXME { printf("FIXME: file %s: line %d", \
__FILE__, \
__LINE__); exit(0); }
#else
#define FIXME
#endif
/*YS*/
static void RBezier_Patch_Normal (VECTOR, OBJECT *, INTERSECTION *);
static int Inside_RBezier_Patch (VECTOR, OBJECT *);
static void Translate_RBezier_Patch (OBJECT *, VECTOR, TRANSFORM *);
static void Scale_RBezier_Patch (OBJECT *, VECTOR, TRANSFORM *);
static void Rotate_RBezier_Patch (OBJECT *, VECTOR, TRANSFORM *);
static void Transform_RBezier_Patch (OBJECT *, TRANSFORM *);
static void Invert_RBezier_Patch (OBJECT *);
static void *Copy_RBezier_Patch (OBJECT *);
static void Destroy_RBezier_Patch (OBJECT *);
void Compute_RBezier_Patch_BBox (RBEZIER_PATCH *);
static int All_RBezier_Patch_Intersections (OBJECT *, RAY *, ISTACK *);
static int rbezier_check_trims (DBL,DBL);
static RAY *Current_Ray;
static RBEZIER_PATCH *Current_Shape;
static ISTACK *Current_Depth_Stack;
static TRIM_SHAPE *Current_Trim;
static int cu_order, cv_order;
static int cu_order_1, cv_order_1;
static int c4_u_order;
static METHODS RBezier_Patch_Methods =
{
All_RBezier_Patch_Intersections,
Inside_RBezier_Patch, RBezier_Patch_Normal, Default_UVCoord,
Copy_RBezier_Patch,
Translate_RBezier_Patch, Rotate_RBezier_Patch,
Scale_RBezier_Patch, Transform_RBezier_Patch, Invert_RBezier_Patch,
Destroy_RBezier_Patch
};
/*******************************************************
(r|)bezier_compute_plane_points_distances functions
********************************************************/
static int bezier_plane_points_distances(DBL p[4][4],VECTOR n,DBL d,RBEZIER_PATCH *Patch)
{
int i, j;
DBL *x,*y,*z;
DBL *ptmp;
DBL a,b,c;
DBL min, max;
ptmp= *p;
x= Patch->pts[X];
y= Patch->pts[Y];
z= Patch->pts[Z];
a= n[X]; b= n[Y]; c=n[Z];
min= INFINITY;
max= -INFINITY;
for ( i= cv_order; i; i--, ptmp+= c4_u_order,
x+=c4_u_order, y+=c4_u_order, z+=c4_u_order)
for ( j= cu_order; j; j--, ptmp++, x++, y++, z++)
{
*ptmp = (*x)*a + (*y)*b + (*z)*c + d;
if (*ptmp < min) min= *ptmp;
if (*ptmp > max) max= *ptmp;
}
if ((min>0.0)||(max<0.0))
return 0;
else
return 1;
}
static int rbezier_plane_points_distances(DBL p[4][4],VECTOR n,DBL d,RBEZIER_PATCH *Patch)
{
int i, j;
DBL *x,*y,*z;
DBL *ptmp, *wptr;
DBL a,b,c;
DBL min, max;
ptmp= *p;
x= Patch->pts[X];
y= Patch->pts[Y];
z= Patch->pts[Z];
wptr= Patch->Weights;
a= n[X]; b= n[Y]; c=n[Z];
min= INFINITY;
max= -INFINITY;
for ( i= cv_order; i; i--, ptmp+= c4_u_order, wptr+=c4_u_order,
x+=c4_u_order, y+=c4_u_order, z+=c4_u_order)
for ( j=cu_order; j; j--, wptr++, ptmp++, x++, y++, z++)
{
*ptmp = (*x)*a + (*y)*b + (*z)*c + (*wptr)*d;
if (*ptmp < min) min= *ptmp;
if (*ptmp > max) max= *ptmp;
}
if ((min>0.0)||(max<0.0))
return 0;
else
return 1;
}
static void
rbezier_precompute_weights(RBEZIER_PATCH *Patch)
{
int i,j;
DBL *x,*y,*z, *wptr;
Patch-> w_precomp=1;
wptr= Patch->Weights;
x= Patch->pts[X];
y= Patch->pts[Y];
z= Patch->pts[Z];
for (i=cv_order; i; i--, x+=c4_u_order, y+=c4_u_order, z+=c4_u_order, wptr+=c4_u_order)
for( j= cu_order; j; j--, wptr++, x++, y++, z++)
{
*x *= *wptr;
*y *= *wptr;
*z *= *wptr;
}
}
/*********************************************************
rbezier_new_line[0|1] functions
**********************************************************/
static int rbezier_new_line0(DISTANCES p[2],DBL Line[2])
{
DBL tmp;
Line[0]= p[1][cv_order_1][0] - p[1][0][0] + p[1][cv_order_1][cu_order_1] - p[1][0][cu_order_1];
Line[1]= - (p[0][cv_order_1][0] - p[0][0][0] + p[0][cv_order_1][cu_order_1] - p[0][0][cu_order_1]);
tmp= Line[0]*Line[0]+Line[1]*Line[1];
if (tmp < VERY_SMALL_EPSILON)
return 0;
tmp= sqrt(tmp);
Line[0]/= tmp;
Line[1]/= tmp;
return 1;
}
static int rbezier_new_line1(DISTANCES p[2],DBL Line[2])
{
DBL tmp;
Line[0]= p[1][0][cu_order_1] - p[1][0][0] + p[1][cv_order_1][cu_order_1] - p[1][cv_order_1][0];
Line[1]= -( p[0][0][cu_order_1] - p[0][0][0] + p[0][cv_order_1][cu_order_1] - p[0][cv_order_1][0] );
tmp= Line[0]*Line[0]+Line[1]*Line[1];
if (tmp < VERY_SMALL_EPSILON)
return 0;
tmp= sqrt (tmp);
Line[0]/= tmp;
Line[1]/= tmp;
return 1;
}
/*********************************************************
rbezier_line_points_distances
**********************************************************/
static void rbezier_line_points_distances(DISTANCES d,DBL vec[2],DISTANCES points[2])
{
int i,j;
DBL a,b;
DBL *ptmp, *xtmp, *ytmp;
a=vec[0];
b=vec[1];
ptmp= *d;
xtmp= **points;
ytmp= *(points[1]);
for (i=cv_order; i;i--,ptmp+=c4_u_order, xtmp+= c4_u_order, ytmp+= c4_u_order)
for (j=cu_order; j; j--, ptmp++, xtmp++, ytmp++)
*ptmp= (*xtmp)*a + (*ytmp)*b;
}
/*********************************************************
rbezier_bounds
**********************************************************/
static int rbezier_bounds( DISTANCES p[2],DBL interval[2][2])
{
int i,j,k;
DBL *itmp;
DBL *min, *max;
int ret=0;
for (i=0; i<2; i++)
{
itmp = &(p[i][0][0]);
min= & (interval[i][0]);
max= & (interval[i][1]);
*min=*max= *(itmp);
for (j= cv_order; j; j--, itmp+= c4_u_order)
for(k= cu_order; k ; k--, itmp++ )
{
if ( *itmp < *min )
*min= *itmp;
else
if ( *itmp > *max )
*max= *itmp;
}
ret|= (*min > EPSILON) || (*max < -EPSILON);
}
return !ret;
}
/*********************************************************
rb_decasteljau_D1_D2 functions
D1 - direction
D2 - order + 1 (ie number of control points
p - points
f - first
s - second
w - where to split
dw - 1.0 - dw
**********************************************************/
#define NEXT_0(T) ((T)++)
#define NEXT_1(T) ((T)+=4)
#define PREV_0(T) ((T)--)
#define PREV_1(T) ((T)-=4)
#define ADD_0(T,X) ((T)+=(X))
#define ADD_1(T,X) ((T)+=(X)*4)
#define AV(F,S) ( dw * (F) + w * (S))
/*
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
(swans)
*/
static void rb_decasteljau_0_2( DBL *p,DBL *f,DBL *s,DBL w,DBL dw,int i)
{
NEXT_0(s);
for(; i; i--)
{
*f= *p;
NEXT_0(p);
*s= *p;
PREV_0(s);
*s= AV( *f,*p );
NEXT_0(f);
*f= *s;
s+= 5;
f+= 3;
p+= 3;
}
}
static void rb_decasteljau_1_2( DBL *p,DBL *f,DBL *s,DBL w,DBL dw,int i)
{
NEXT_1(s);
for(; i; i--)
{
*f= *p;
NEXT_1(p);
*s= *p;
PREV_1(s);
*s= AV( *f,*p );
NEXT_1(f);
*f= *s;
s+= 5;
f-= 3;
p-= 3;
}
}
/*
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
.....
*/
static void rb_decasteljau_0_3( DBL *p,DBL *f,DBL *s,DBL w,DBL dw,int i)
{
ADD_0( s , 2);
for (; i ; i--)
{
*f= *p;
NEXT_0(f);
*f= AV( *p, *(p+1));
ADD_0( p, 2);
*s= *p;
PREV_0(s);
*s= AV( *(p-1), *p);
PREV_0(s);
*s= AV( *f, *(s+1) );
NEXT_0(f);
*f= *s;
f+= 2;
p+= 2;
s+= 6;
}
}
static void rb_decasteljau_1_3( DBL *p,DBL *f,DBL *s,DBL w,DBL dw,int i)
{
ADD_1( s , 2 );
for (; i ; i--)
{
*f= *p;
NEXT_1(f);
*f= AV( *p, *(p+4));
ADD_1( p, 2);
*s= *p;
PREV_1(s);
*s= AV( *(p-4), *p);
PREV_1(s);
*s= AV( *f, *(s+4) );
NEXT_1(f);
*f= *s;
f+= 1 - 2 * 4;
p+= 1 - 2 * 4;
s+= 1 + 2 * 4;
}
}
/*
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
(chairs)
*/
static void rb_decasteljau_0_4( DBL *p,DBL *f,DBL *s,DBL w,DBL dw,int i)
{
DBL tmp;
ADD_0( s, 3 );
for (; i; i--)
{
*f= *p;
NEXT_0(f);
*f= AV(*p, *(p+1));
NEXT_0(f);
NEXT_0(p);
tmp= AV(*p, *(p+1));
*f= AV(*(f-1), tmp );
NEXT_0(p);
*s= *(p+1);
PREV_0( s );
*s= AV( *p, *(s+1) );
PREV_0( s );
*s= AV( tmp, *(s+1));
PREV_0(s);
*s= AV( *f, *(s+1) );
NEXT_0(f);
*f=*s;
f++;
p+= 2; /* p was on [.][2] */
s+= 7;
}
}
static void rb_decasteljau_1_4( DBL *p,DBL *f,DBL *s,DBL w,DBL dw,int i)
{
DBL tmp;
ADD_1( s, 3);
for (; i; i--)
{
*f= *p;
NEXT_1(f);
*f= AV(*p, *(p+4));
NEXT_1(f);
NEXT_1(p);
tmp= AV(*p, *(p+4));
*f= AV(*(f-4), tmp);
NEXT_1(p);
*s= *(p+4);
PREV_1( s );
*s= AV( *p, *(s+4) );
PREV_1( s );
*s= AV( tmp, *(s+4));
PREV_1(s);
*s= AV( *f, *(s+4) );
NEXT_1(f);
*f=*s;
f+= 1 - 3 * 4;
p+= 1 - 2 * 4; /* p was on [2][.] */
s+= 1 + 3 * 4;
}
}
/*********************************************************
rbezier_get_minmax_D1_D2 functions
**********************************************************/
#define FIND_INTER( P, N, P0, N0 ) \
if ( ( (P) <= 0.0) ^ ( (N) <= 0.0) ) \
{ \
tmp= (P0) + ((N0)-(P0)) * (P) / ( (P) - (N) ); \
\
if (tmp < *min) *min= tmp; \
if (tmp > *max) *max= tmp; \
}
static int rb_get_minmax_0_2(DISTANCES d,DBL *min, DBL *max)
{
DBL *n,*p,tmp;
int f,l;
int i;
*min = 2.0;
*max =-2.0;
n= 1 + ( p= *d );
f=l=0;
for (i= cv_order; i; i--, NEXT_1(p), NEXT_1(n))
{
if ( *p < 0.0) f++;
if ( *n < 0.0) l++;
FIND_INTER( *p, *n, 0.0, 1.0 );
}
if (( f != 0 ) && ( f != cv_order )) *min = 0.0;
if (( l != 0 ) && ( l != cv_order )) *max = 1.0;
return ( *min <= * max );
}
static int rb_get_minmax_1_2(DISTANCES d,DBL *min, DBL *max)
{
DBL *n,*p,tmp;
int f,l;
int i;
*min = 2.0;
*max =-2.0;
n= 4 + ( p= *d );
f=l=0;
for (i= cu_order; i; i--, NEXT_0(p), NEXT_0(n))
{
if ( *p < 0.0) f++;
if ( *n < 0.0) l++;
FIND_INTER( *p, *n, 0.0, 1.0 );
}
if (( f != 0 ) && ( f != cu_order )) *min = 0.0;
if (( l != 0 ) && ( l != cu_order )) *max = 1.0;
return ( *min <= * max );
}
static int rb_get_minmax_0_3(DISTANCES d,DBL *min, DBL *max)
{
DBL *n,*p, *m,tmp;
int f,l;
int i;
*min = 2.0;
*max =-2.0;
n= ( 1+ (m= 1 + ( p= *d )));
f=l=0;
for (i= cv_order; i; i--, NEXT_1(p), NEXT_1(m), NEXT_1(n))
{
if ( *p < 0.0) f++;
if ( *n < 0.0) l++;
FIND_INTER( *p, *m, 0.0, 0.5 );
FIND_INTER( *m, *n, 0.5, 1.0 );
FIND_INTER( *p, *n, 0.0, 1.0 );
}
if (( f != 0 ) && ( f != cv_order )) *min = 0.0;
if (( l != 0 ) && ( l != cv_order )) *max = 1.0;
return ( *min <= * max );
}
static int rb_get_minmax_1_3(DISTANCES d,DBL *min, DBL *max)
{
DBL *n,*p, *m,tmp;
int f,l;
int i;
*min = 2.0;
*max =-2.0;
n= ( 4 + (m= 4 + ( p= *d )));
f=l=0;
for (i= cu_order; i; i--, NEXT_0(p), NEXT_0(m), NEXT_0(n))
{
if ( *p < 0.0) f++;
if ( *n < 0.0) l++;
FIND_INTER( *p, *m, 0.0, 0.5 );
FIND_INTER( *m, *n, 0.5, 1.0 );
FIND_INTER( *p, *n, 0.0, 1.0 );
}
if (( f != 0 ) && ( f != cu_order )) *min = 0.0;
if (( l != 0 ) && ( l != cu_order )) *max = 1.0;
return ( *min <= * max );
}
static int rb_get_minmax_0_4(DISTANCES d,DBL *min, DBL *max)
{
DBL *n,*p, *mn, *mp,tmp;
int f,l;
int i;
*min = 2.0;
*max =-2.0;
n= 1 + (mn= 1+ (mp= 1 + ( p= *d )));
f=l=0;
for (i= cv_order; i; i--, NEXT_1(p), NEXT_1(mp), NEXT_1(mn), NEXT_1(n))
{
if ( *p < 0.0) f++;
if ( *n < 0.0) l++;
FIND_INTER( * p, *mp, 0.0, (1.0/3.0) );
FIND_INTER( *mp, *mn, (1.0/3.0), (2.0/3.0) );
FIND_INTER( * p, *mn, 0.0, (2.0/3.0) );
FIND_INTER( *mn, * n, (2.0/3.0), 1.0 );
FIND_INTER( *mp, * n, (1.0/3.0), 1.0 );
FIND_INTER( * p, * n, 0.0 , 1.0 );
}
if (( f != 0 ) && ( f != cv_order )) *min = 0.0;
if (( l != 0 ) && ( l != cv_order )) *max = 1.0;
return ( *min <= * max );
}
static int rb_get_minmax_1_4(DISTANCES d,DBL *min, DBL *max)
{
DBL *n,*p, *mn, *mp,tmp;
int f,l;
int i;
*min = 2.0;
*max =-2.0;
n= 4 + (mn= 4+ (mp= 4 + ( p= *d )));
f=l=0;
for (i= cu_order; i; i--, NEXT_0(p), NEXT_0(mp), NEXT_0(mn), NEXT_0(n))
{
if ( *p < 0.0) f++;
if ( *n < 0.0) l++;
FIND_INTER( * p, *mp, 0.0, (1.0/3.0) );
FIND_INTER( *mp, *mn, (1.0/3.0), (2.0/3.0) );
FIND_INTER( * p, *mn, 0.0, (2.0/3.0) );
FIND_INTER( *mn, * n, (2.0/3.0), 1.0 );
FIND_INTER( *mp, * n, (1.0/3.0), 1.0 );
FIND_INTER( * p, * n, 0.0 , 1.0 );
}
if (( f != 0 ) && ( f != cu_order )) *min = 0.0;
if (( l != 0 ) && ( l != cu_order )) *max = 1.0;
return ( *min <= * max );
}
static
int (*rbezier_get_minmax[2][4])(DISTANCES, DBL*, DBL*)= {
{ NULL, rb_get_minmax_0_2, rb_get_minmax_0_3, rb_get_minmax_0_4 },
{ NULL, rb_get_minmax_1_2, rb_get_minmax_1_3, rb_get_minmax_1_4 }
};
static
void (*rbezier_decasteljau[2][4])(DBL*, DBL*, DBL *, DBL, DBL, int ) = {
{ NULL, rb_decasteljau_0_2, rb_decasteljau_0_3, rb_decasteljau_0_4 },
{ NULL, rb_decasteljau_1_2, rb_decasteljau_1_3, rb_decasteljau_1_4 }
};
/**************************************************
rbezier_point
**************************************************/
static void rbezier_point(DBL u,DBL v,int iii,DBL *cp,DBL *p0,DBL *p10,DBL *p11 )
{
DISTANCES d1, d2;
if (iii == 0)
{
rbezier_decasteljau[0][cu_order_1]( cp, &(d1[0][0]), &(d2[0][0]),u,1.0-u, cv_order);
rbezier_decasteljau[1][cv_order_1]( &(d2[0][0]), &(d2[0][1]), &(d2[0][2]), v, 1.0-v, 1);
*p0= d2[0][2];
*p10= d2[1][2];
*p11= d2[cv_order - 2][1];
}
else
{
rbezier_decasteljau[1][cv_order_1]( cp, &(d1[0][0]), &(d2[0][0]),v,1.0-v, cu_order);
rbezier_decasteljau[0][cu_order_1]( &(d2[0][0]), &(d2[1][0]), &(d2[2][0]), u, 1.0-u, 1);
*p0= d2[2][0];
*p10= d2[2][1];
*p11= d2[1][cu_order - 2];
}
}
/**************************************************
rbezier_add_solution
**************************************************/
static int rbezier_add_solution(DBL u,DBL v)
{
int coord;
DBL *cp, d;
int iii;
DBL c1,c2,c3;
DBL w1,w2,w3;
VECTOR IPoint;
ISTACK *i;
if ((u<0.0) || (u> 1.0) || (v < 0.0) || ( v > 1.0)) return 0;
if (fabs(Current_Ray->Direction[X]) > 0.5 )
{ coord= X; cp = Current_Shape -> pts[X]; }
else
if (fabs(Current_Ray->Direction[Y]) > 0.5 )
{ coord= Y; cp = Current_Shape -> pts[Y]; }
else
{ coord= Z; cp = Current_Shape -> pts[Z]; }
iii= cu_order > cv_order;
rbezier_point( u, v, iii, cp, &c1, &c2, &c3);
if ( Current_Shape -> Weights )
{
rbezier_point( u, v, iii, Current_Shape->Weights, &w1, &w2, &w3 );
c1/= w1;
c2= (c2 / w2 - c3 / w3);
}
else
c2= c2 -c3;
d= (c1 - Current_Ray->Initial[coord]) / (Current_Ray->Direction[coord]);
if ( d < 4.0 * Current_Shape -> accuracy) return 0;
if (Current_Shape->num_of_trims != 0)
if (rbezier_check_trims(u,v) == 0) return 0;
VScale (IPoint, Current_Ray->Direction, d);
VAddEq (IPoint, Current_Ray->Initial);
i= Current_Depth_Stack;
/*
I was too lazy to create own macro in frame.h :-)
so you can imagine this is macro push_entry_blah_blah
*/
itop(i).Depth = d;
itop(i).Object = (OBJECT *) Current_Shape;
itop(i).i1 = coord;
itop(i).i2 = iii;
itop(i).u = u;
itop(i).v = v;
itop(i).d1 = c1;
itop(i).d2 = c2;
if (Current_Shape -> Weights)
{
itop(i).w1 = w1;
itop(i).w2 = w2;
itop(i).w3 = w3;
}
Assign_Vector(itop(i).IPoint,IPoint);
incstack(i);
/* end of `virtual' macro :-) */
return 1;
}
/*********************************************************
rbezier_find_solution
**********************************************************/
static int rbezier_find_solution( DISTANCES p[2],DBL interval[2][2], DBL bounds[2][2])
{
int iii, yyy,ppp;
DBL Line[2];
DBL tmp;
char in_half=0;
DISTANCES d;
DBL min,max;
if ( (bounds[1][1]-bounds[1][0] < Current_Shape->accuracy)
&& (bounds[0][1]-bounds[0][0] < Current_Shape->accuracy))
{ /* end of iteration ...*/
return rbezier_add_solution( interval[0][0]+ interval[0][1]/2.0, interval[1][0] + interval[1][1]/2.0 );
FIXME /* soupni sem presnejsi resitko ...!!! */
}
if ( interval[0][1] > interval[1][1] )
{
iii=0;
if ( rbezier_new_line0(p, Line) == 0)
if ( rbezier_new_line1(p, Line) == 0)
in_half=1; /* degenerated patch -=> split in half */
else
{
tmp= -Line[0];
Line[0]= Line[1];
Line[1]= tmp;
}
}
else
{
iii=1;
if ( rbezier_new_line1(p, Line) == 0)
if ( rbezier_new_line0(p, Line) == 0)
in_half=1; /* degenerated patch -=> split in half */
else
{
tmp= -Line[0];
Line[0]= Line[1];
Line[1]= tmp;
}
}
yyy= (iii == 0) ? cu_order_1 : cv_order_1;
ppp= (iii != 0) ? cu_order : cv_order;
if (in_half == 0)
{
rbezier_line_points_distances( d, Line, p);
if ( rbezier_get_minmax[iii][yyy](d,&min, &max)==0) return 0;
if ( (tmp= max-min) > MAGICAL_CONSTANT )
in_half= 1;
else
{
{
DISTANCES ptmp1[2],ptmp2[2];
if (min < 0.5)
{
rbezier_decasteljau[iii][yyy]( &(p[0][0][0]), &(ptmp1[0][0][0]), &(ptmp2[0][0][0]), min, 1.0 - min, ppp);
rbezier_decasteljau[iii][yyy]( &(p[1][0][0]), &(ptmp1[1][0][0]), &(ptmp2[1][0][0]), min, 1.0 - min, ppp);
rbezier_decasteljau[iii][yyy]( &(ptmp2[0][0][0]), &(p[0][0][0]), &(ptmp1[0][0][0]),
(max-min) / (1.0 - min), (1.0 - max) / (1.0 - min), ppp);
rbezier_decasteljau[iii][yyy]( &(ptmp2[1][0][0]), &(p[1][0][0]), &(ptmp1[1][0][0]),
(max-min) / (1.0 - min), (1.0 - max) / (1.0 - min), ppp);
}
else
{
rbezier_decasteljau[iii][yyy]( &(p[0][0][0]), &(ptmp1[0][0][0]), &(ptmp2[0][0][0]), max, 1.0 - max, ppp);
rbezier_decasteljau[iii][yyy]( &(p[1][0][0]), &(ptmp1[1][0][0]), &(ptmp2[1][0][0]), max, 1.0 - max, ppp);
rbezier_decasteljau[iii][yyy]( &(ptmp1[0][0][0]), &(ptmp2[0][0][0]), &(p[0][0][0]),
min / max, 1.0 - min / max, ppp);
rbezier_decasteljau[iii][yyy]( &(ptmp1[1][0][0]), &(ptmp2[1][0][0]), &(p[1][0][0]),
min / max, 1.0 - min/max, ppp);
}
}
if (rbezier_bounds(p, bounds ) == 0) return 0;
interval[iii][0]+= interval[iii][1]*min;
interval[iii][1] = interval[iii][1]*tmp;
return rbezier_find_solution(p, interval, bounds);
}
}
/* (in_half == 1) */
{
DISTANCES ld[2], rd[2];
DBL ni[2][2];
int ret=0;
rbezier_decasteljau[iii][yyy]( &(p[0][0][0]), &(ld[0][0][0]), &(rd[0][0][0]), 0.5, 0.5 ,ppp);
rbezier_decasteljau[iii][yyy]( &(p[1][0][0]), &(ld[1][0][0]), &(rd[1][0][0]), 0.5, 0.5 ,ppp);
tmp= interval[iii][1]/= 2.0;
memcpy( &(ni[0][0]), &(interval[0][0]), 4 * sizeof(DBL));
ni[iii][0]+= tmp;
if (rbezier_bounds(ld,bounds) != 0)
ret|= rbezier_find_solution(ld, interval, bounds);
if (rbezier_bounds(rd, bounds) != 0)
ret|= rbezier_find_solution(rd, ni, bounds);
return ret;
}
}
/*********************************************************
All_RBezier_Patch_Intersections
**********************************************************/
static int All_RBezier_Patch_Intersections(OBJECT *Object,RAY *Ray,ISTACK *Depth_Stack)
{
VECTOR n0,n1;
DBL d0, d1;
DISTANCES p[2];
DBL interval[2][2];
DBL sti[2][2];
RBEZIER_PATCH *Patch;
int ret;
#ifdef DEBUG_RBEZIER
if (((RBEZIER_PATCH *)Object)->debug)
if (Ray->Direction[Z] != 1.0) return 0;
#endif
Increase_Counter(stats[Ray_RBezier_Tests]);
Patch= (RBEZIER_PATCH *) Object;
find_planes( Ray->Initial, Ray->Direction, n0,&d0,n1,&d1);
cu_order= Patch->u_order;
cv_order= Patch->v_order;
cu_order_1= cu_order-1;
cv_order_1= cv_order-1;
c4_u_order= 4 - cu_order;
if ( Patch -> Weights == NULL)
{
if (bezier_plane_points_distances(p[0], n0, d0, Patch) == 0)
return 0;
if (bezier_plane_points_distances(p[1], n1, d1, Patch) == 0)
return 0;
}
else
{
if (Patch-> w_precomp == 0)
{
rbezier_precompute_weights(Patch);
}
if (rbezier_plane_points_distances(p[0], n0, d0, Patch) == 0)
return 0;
if (rbezier_plane_points_distances(p[1], n1, d1, Patch) == 0)
return 0;
}
interval[0][0]=interval[1][0]= 0.0;
if ( cu_order > cv_order)
{
/* small trick to ensure that we first split patch in
smaller order */
interval[0][1]= 1.0 + YAEP;
interval[1][1]= 1.0;
}
else
{
interval[0][1]= 1.0;
interval[1][1]= 1.0 + YAEP;
}
sti[1][1]= sti[0][1]= INFINITY;
sti[1][0]= sti[0][0]= -INFINITY;
Current_Ray= Ray;
Current_Shape= Patch;
Current_Depth_Stack= Depth_Stack;
ret= rbezier_find_solution( p, interval, sti );
if (ret)
Increase_Counter(stats[Ray_RBezier_Tests_Succeeded]);
return ret;
}
static void RBezier_Patch_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
{
VECTOR v1,v2;
int i, rat;
DBL u,v;
DBL c1,c2,c3;
DBL w1,w2,w3;
RBEZIER_PATCH *Patch;
int iii;
Patch= (RBEZIER_PATCH *) Object;
cu_order= Patch-> u_order;
cv_order= Patch-> v_order;
cu_order_1= cu_order-1;
cv_order_1= cv_order-1;
iii= Inter-> i2;
u= Inter->u;
v= Inter->v;
if ( (rat= (Patch ->Weights != NULL)))
{ w2= Inter->w2; w3= Inter->w3; }
for ( i = 0; i <=Z; i++)
if ( i == Inter -> i1 ) /* computed in rbezier_add_solution */
v1[i]= Inter->d2;
else
{
rbezier_point( u, v, iii, Patch->pts[i], &c1, &c2, &c3);
if (rat)
v1[i]= (c2 / w2 - c3 / w3 );
else
v1[i]= c2 - c3;
}
iii^= 1;
if (rat)
rbezier_point( u, v, iii, Patch->Weights, &w1, &w2, &w3);
for ( i = 0; i <=Z; i++)
{
rbezier_point( u, v, iii, Patch->pts[i], &c1, &c2, &c3);
if (rat)
v2[i]= (c2 / w2 - c3 / w3 );
else
v2[i]= c2 - c3;
}
VCross(Result, v1,v2);
VLength(w2, Result);
if (w2 < VERY_SMALL_EPSILON)
{ Result[X]= Result[Y]= 0.0; Result[Z]= 1.0; }
else
{ Result[X]/= w2; Result[Y]/= w2; Result[Z]/= w2; }
}
/***********************************************************
other "not so funny functions" (like transform, create etc)
************************************************************/
static int Inside_RBezier_Patch(VECTOR IPoint,OBJECT *Object)
{
return (0);
}
static void Translate_RBezier_Patch(OBJECT *Object,VECTOR Vector,TRANSFORM *Trans)
{
int i,n;
RBEZIER_PATCH *Patch = (RBEZIER_PATCH *) Object;
n= 4 * Patch -> v_order;
for (i=0; i < n; i++)
{
Patch->Points[X*n+i]+= Vector[X];
Patch->Points[Y*n+i]+= Vector[Y];
Patch->Points[Z*n+i]+= Vector[Z];
}
Compute_RBezier_Patch_BBox(Patch);
}
static void Scale_RBezier_Patch(OBJECT *Object,VECTOR Vector,TRANSFORM *Trans)
{
int i,n;
RBEZIER_PATCH *Patch = (RBEZIER_PATCH *) Object;
n= 4 * Patch-> v_order;
for (i=0; i < n; i++)
{
Patch->Points[X*n+i]*= Vector[X];
Patch->Points[Y*n+i]*= Vector[Y];
Patch->Points[Z*n+i]*= Vector[Z];
}
Compute_RBezier_Patch_BBox(Patch);
}
static void Rotate_RBezier_Patch (OBJECT *Object,VECTOR Vector,TRANSFORM *Trans)
{
Transform_RBezier_Patch(Object, Trans);
}
static void Transform_RBezier_Patch(OBJECT *Object,TRANSFORM *Trans)
{
int i,n;
VECTOR v;
RBEZIER_PATCH *Patch = (RBEZIER_PATCH *) Object;
n= 4 * Patch->v_order;
for (i = 0; i < n; i++)
{
v[X]= Patch->Points[X*n+i];
v[Y]= Patch->Points[Y*n+i];
v[Z]= Patch->Points[Z*n+i];
MTransPoint(v, v, Trans);
Patch->Points[X*n+i]= v[X];
Patch->Points[Y*n+i]= v[Y];
Patch->Points[Z*n+i]= v[Z];
}
Compute_RBezier_Patch_BBox (Patch);
}
static void Invert_RBezier_Patch(OBJECT *Object)
{
}
RBEZIER_PATCH *Create_RBezier_Patch(void)
{
RBEZIER_PATCH *New;
New= (RBEZIER_PATCH *) POV_MALLOC ( sizeof (RBEZIER_PATCH), "bezier patch" );
INIT_OBJECT_FIELDS(New, RBEZIER_PATCH_OBJECT, &RBezier_Patch_Methods)
New-> Points= NULL;
New-> Weights= NULL;
New-> trims= NULL;
New-> num_of_trims= 0;
New-> w_precomp= 0;
New-> u_order= 4;
New-> v_order= 4;
New-> accuracy= 0.01;
#ifdef DEBUG_RBEZIER
New-> debug= 0;
#endif
return (New);
}
static void *Copy_RBezier_Patch(OBJECT *Object)
{
RBEZIER_PATCH *New, *Old;
int i;
New= Create_RBezier_Patch();
Old= (RBEZIER_PATCH *) Object;
New->UV_Trans = Copy_Transform( Old->UV_Trans );
New->accuracy= Old->accuracy;
New->u_order= Old-> u_order;
New->v_order= Old-> v_order;
i= 4 * Old-> v_order;
if (Old -> Points)
{
New->Points= (DBL *) POV_MALLOC( sizeof(DBL) * (i * 3), "bezier patch");
memcpy ( New->Points, Old->Points, sizeof(DBL) * (i * 3) );
}
if (Old -> Weights)
{
New->Weights= (DBL *) POV_MALLOC ( sizeof(DBL) * i, "bezier patch");
memcpy( New->Points, Old->Points, sizeof(DBL) * i);
}
New->pts[X]= New->Points;
New->pts[Y]= &(New->Points[4*New->v_order]);
New->pts[Z]= &(New->Points[2*4*New->v_order]);
if (New-> num_of_trims != 0)
{
for (i=New->num_of_trims; i; i--)
{
Copy_Trim( New->trims[i] );
/* just to incremetn counter in trim */
}
}
return (New);
}
static void Destroy_RBezier_Patch(OBJECT *Object)
{
RBEZIER_PATCH *Patch;
int i;
Patch = (RBEZIER_PATCH *)Object;
if ( Patch -> Points ) POV_FREE( Patch-> Points );
if ( Patch -> Weights ) POV_FREE( Patch -> Weights );
if (Patch -> trims)
{
for (i= 0; i < Patch->num_of_trims; i++)
Destroy_Trim( Patch -> trims[i] );
POV_FREE( Patch->trims );
}
POV_FREE( Patch );
}
void Compute_RBezier_Patch_BBox(RBEZIER_PATCH *Patch)
{
int i,n;
VECTOR Min, Max;
Make_Vector(Min, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
Make_Vector(Max, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
n= 4 * (Patch-> v_order);
for (i=0; i < n; i++)
{
Min[X] = min(Min[X], Patch->Points[X*n+i]);
Min[Y] = min(Min[Y], Patch->Points[Y*n+i]);
Min[Z] = min(Min[Z], Patch->Points[Z*n+i]);
Max[X] = max(Max[X], Patch->Points[X*n+i]);
Max[Y] = max(Max[Y], Patch->Points[Y*n+i]);
Max[Z] = max(Max[Z], Patch->Points[Z*n+i]);
}
Make_BBox_from_min_max( Patch-> BBox, Min, Max);
}
/*******************************************************
functon for handling trimmed surface
*******************************************************/
/**************************************************
rbezier_trim
**************************************************/
static int trim_choose_direction( DBL u,DBL v )
{
char dir;
DBL min, tmp;
dir=0;
min= Current_Trim-> bounds[0][1] - u ;
tmp= u - Current_Trim-> bounds[0][0];
if ( min > tmp ) { min= tmp; dir = 2; }
tmp= Current_Trim-> bounds[1][1] - v;
if ( min > tmp ) { min= tmp; dir = 1; }
tmp= v - Current_Trim-> bounds[1][0];
if ( min > tmp ) { min= tmp; dir = 3; }
if (min < 0.0) return -1;
else return dir;
}
static void trim_translate_points(char dir,DBL u,DBL v,DBL *newu,DBL *newv)
{
int i;
DBL *uu, *vv;
uu= Current_Trim-> u;
vv= Current_Trim-> v;
if ((dir & 1) == 0)
if (dir==0)
for (i=Current_Trim->num_of_cp; i; *newu=(*uu)-u, (*newv)=(*vv)-v, uu++, vv++, newu++, newv++, i--);
else
for (i=Current_Trim->num_of_cp; i; *newu=u-(*uu), (*newv)=v-(*vv), uu++, vv++, newu++, newv++, i--);
else
if (dir==1)
for (i=Current_Trim->num_of_cp; i; *newu=(*vv)-v, (*newv)=(*uu)-u, uu++, vv++, newu++, newv++, i--);
else
for (i=Current_Trim->num_of_cp; i; *newu=v-(*vv), (*newv)=u-(*uu), uu++, vv++, newu++, newv++, i--);
}
#define TRIM_FIND_INTER( P, N, P0, N0 ) \
{ \
tmp= (P0) + ((N0)-(P0)) * (P) / ( (P) - (N) ); \
\
if (tmp < min) min= tmp; \
if (tmp > max) max= tmp; \
}
static int trim_check_3 (DBL *uu, DBL *vv,DBL len)
{
int vc,vcc, uc;
DBL min, max, tmp;
vc= (vv[0]<0.0) + (vv[2]<0.0);
vcc= vc + (vv[1]<0.0);
if ((vcc==0)||(vcc==3)) return 0;
uc= (uu[0]<0.0) + (uu[1]<0.0) + (uu[2]<0.0);
if (uc==3) return 0;
if (uc ==0)
if (vc==1)
return 1;
else /* vc from {0,2} */
return 0;
/*
if (len < Current_Shape->accuracy) return 0;
*/
min= 2; max= -2;
if ((vv[0]<0.0)^(vv[1]<0.0))
TRIM_FIND_INTER( vv[0], vv[1], 0.0, 0.5);
if ((vv[1]<0.0)^(vv[2]<0.0))
TRIM_FIND_INTER( vv[1], vv[2], 0.5, 1.0);
if (vc == 1)
TRIM_FIND_INTER( vv[0], vv[2], 0.0, 1.0);
if (min > max) return 0;
if ((max-min) < Current_Shape->accuracy)
{ /* size of new part would be too small -=> stop */
DBL uu1[3], uu2[3], vv1[3], vv2[3];
rb_decasteljau_0_3( uu, uu1, uu2, min, 1.0-min, 1);
rb_decasteljau_0_3( vv, vv1, vv2, min, 1.0-min, 1);
if ((uu2[0] >= 0.0) && (fabs(vv2[0]) < Current_Shape-> accuracy)) return 1;
else return 0;
}
if ((max-min) > MAGICAL_CONSTANT)
{ /* split in half */
DBL uu1[3], uu2[3], vv1[3],vv2[3];
rb_decasteljau_0_3( uu, uu1, uu2, 0.5, 0.5, 1);
rb_decasteljau_0_3( vv, vv1, vv2, 0.5, 0.5, 1);
return trim_check_3(uu1, vv1, 0.5 * len)
+ trim_check_3(uu2, vv2, 0.5 * len);
}
else
{
DBL uu1[3], uu2[3], uu3[3], vv1[3], vv2[3], vv3[3];
if (min < 0.5)
{
rb_decasteljau_0_3( uu, uu1, uu2, min, 1.0-min, 1);
rb_decasteljau_0_3( vv, vv1, vv2, min, 1.0-min, 1);
rb_decasteljau_0_3( uu2, uu1, uu3, (max-min)/(1.0-min), (1.0-max)/(1.0-min), 1);
rb_decasteljau_0_3( vv2, vv1, vv3, (max-min)/(1.0-min), (1.0-max)/(1.0-min), 1);
return trim_check_3( uu1, vv1, len * (max-min) );
}
else
{
rb_decasteljau_0_3( uu, uu1, uu2, max, 1.0-max, 1);
rb_decasteljau_0_3( vv, vv1, vv2, max, 1.0-max, 1);
rb_decasteljau_0_3( uu1, uu2, uu3, min / max, 1.0 - min / max, 1);
rb_decasteljau_0_3( vv1, vv2, vv3, min / max, 1.0 - min / max, 1);
return trim_check_3( uu3, vv3, len * (max-min) );
}
}
}
static int trim_check_4 (DBL *uu, DBL *vv,DBL len)
{
int vc,vcc, uc;
DBL min, max, tmp;
vc= (vv[0]<0.0) + (vv[3]<0.0);
vcc= vc + (vv[1]<0.0) + (vv[2]<0.0);
if ((vcc==0)||(vcc==4)) return 0;
uc= (uu[0]<0.0) + (uu[1]<0.0) + (uu[2]<0.0) + (uu[3]<0.0);
if (uc==4) return 0;
if (uc ==0)
if (vc==1)
return 1;
else /* vc from {0,2} */
return 0;
/* seems that following check is useless. Moreover it seems that it's originator of some bad results
if (len < Current_Shape->accuracy) return 0;
*/
min= 2; max= -2;
if ((vv[0]<0.0)^(vv[1]<0.0))
TRIM_FIND_INTER( vv[0], vv[1], 0.0, 1.0/3.0);
if ((vv[1]<0.0)^(vv[2]<0.0))
TRIM_FIND_INTER( vv[1], vv[2], 1.0/3.0, 2.0/3.0);
if ((vv[2]<0.0)^(vv[3]<0.0))
TRIM_FIND_INTER( vv[2], vv[3], 2.0/3.0, 1.0);
if ((vv[0]<0.0)^(vv[2]<0.0))
TRIM_FIND_INTER( vv[0], vv[2], 0.0, 2.0/3.0);
if ((vv[1]<0.0)^(vv[3]<0.0))
TRIM_FIND_INTER( vv[1], vv[3], 1.0/3.0, 1.0);
if (vc == 1)
TRIM_FIND_INTER( vv[0], vv[3], 0.0, 1.0);
if (min > max) return 0;
if ((max-min) < Current_Shape->accuracy)
{ /* size of new part would be too small -=> stop */
DBL uu1[4], uu2[4],vv1[4], vv2[4];
rb_decasteljau_0_4( uu, uu1, uu2, min, 1.0-min, 1);
rb_decasteljau_0_4( vv, vv1, vv2, min, 1.0-min, 1);
if ((uu2[0] >= 0.0) && (fabs(vv2[0]) < Current_Shape-> accuracy)) return 1;
else return 0;
}
if ((max-min) > MAGICAL_CONSTANT)
{ /* split in half */
DBL uu1[4], uu2[4], vv1[4],vv2[4];
rb_decasteljau_0_4( uu, uu1, uu2, 0.5, 0.5, 1);
rb_decasteljau_0_4( vv, vv1, vv2, 0.5, 0.5, 1);
return trim_check_4(uu1, vv1, 0.5 * len)
+ trim_check_4(uu2, vv2, 0.5 * len);
}
else
{
DBL uu1[4], uu2[4], uu3[4], vv1[4], vv2[4], vv3[4];
if (min < 0.5)
{
rb_decasteljau_0_4( uu, uu1, uu2, min, 1.0-min, 1);
rb_decasteljau_0_4( vv, vv1, vv2, min, 1.0-min, 1);
rb_decasteljau_0_4( uu2, uu1, uu3, (max-min)/(1.0-min), (1.0-max)/(1.0-min), 1);
rb_decasteljau_0_4( vv2, vv1, vv3, (max-min)/(1.0-min), (1.0-max)/(1.0-min), 1);
return trim_check_4( uu1, vv1, len * (max-min) );
}
else
{
rb_decasteljau_0_4( uu, uu1, uu2, max, 1.0-max, 1);
rb_decasteljau_0_4( vv, vv1, vv2, max, 1.0-max, 1);
rb_decasteljau_0_4( uu1, uu2, uu3, min / max, 1.0 - min / max, 1);
rb_decasteljau_0_4( vv1, vv2, vv3, min / max, 1.0 - min / max, 1);
return trim_check_4( uu3, vv3, len * (max-min) );
}
}
}
#define CONTINUE_2 uu++; vv++; continue;
#define CONTINUE_3 uu+=2; vv+=2; continue;
#define CONTINUE_4 uu+=3; vv+=3; continue;
static int trim_check (TRIM_SHAPE *trim, DBL u,DBL v)
{
char dir, *cc;
DBL up[TRIM_MAX_CONST], vp[TRIM_MAX_CONST];
DBL *uu,*vv, *ww;
int i, inter, tmpi;
Current_Trim= trim;
inter= trim->ttype;
if ((dir= trim_choose_direction(u,v)) < 0) return inter;
trim_translate_points(dir, u,v, up, vp);
uu= up; vv= vp; ww= trim->w; cc= trim->ctypes;
for (i=trim->num_of_parts; i; i--, cc++)
switch ( (*cc) & 0x0f )
{
case 2: /* 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */
tmpi= (vv[0] < 0.0) + (vv[1] < 0.0);
if ((tmpi & 1)==0) { CONTINUE_2 }
tmpi= (uu[0] < 0.0) + (uu[1] < 0.0);
if (tmpi == 2) { CONTINUE_2 }
if (tmpi == 0) { inter++; CONTINUE_2 }
if ( 0.0 >= (
uu[0] + ((uu[1]-uu[0]) * (vv[0])) / (vv[0] - vv[1])
)) { CONTINUE_2 }
inter++;
CONTINUE_2
case 3:
if (((*cc) & 0xf0) == 0)
{
inter+= trim_check_3(uu, vv,1.0);
CONTINUE_3;
}
else
{
DBL u1[3], v1[3];
u1[0]= (*ww) * (*uu); v1[0]= (*ww) * (*vv); ww++; uu++; vv++;
u1[1]= (*ww) * (*uu); v1[1]= (*ww) * (*vv); ww++; uu++; vv++;
u1[2]= (*ww) * (*uu); v1[2]= (*ww) * (*vv); ww++;
inter += trim_check_3(u1, v1,1.0);
continue;
}
case 4:
if (((*cc) & 0xf0) == 0)
{
inter+= trim_check_4(uu, vv,1.0);
CONTINUE_4;
}
else
{
DBL u1[4], v1[4];
u1[0]= (*ww) * (*uu); v1[0]= (*ww) * (*vv); ww++; uu++; vv++;
u1[1]= (*ww) * (*uu); v1[1]= (*ww) * (*vv); ww++; uu++; vv++;
u1[2]= (*ww) * (*uu); v1[2]= (*ww) * (*vv); ww++; uu++; vv++;
u1[3]= (*ww) * (*uu); v1[3]= (*ww) * (*vv); ww++;
inter += trim_check_4(u1, v1,1.0);
continue;
}
default:
Error("This trim is not implemented yet");
}
return inter;
}
static int rbezier_check_trims(DBL u,DBL v)
{
int i;
for (i=0; i < Current_Shape->num_of_trims; i++)
if ( (trim_check((Current_Shape->trims)[i], u, v) & 1) == 0)
return 0;
return 1;
}
void Destroy_Trim( TRIM_SHAPE *ptr)
{
(ptr->refs)--;
if (ptr->refs == 0)
{
POV_FREE( ptr-> u );
POV_FREE( ptr );
}
}
TRIM_SHAPE *Copy_Trim (TRIM_SHAPE *trim)
{
if (trim==NULL) return NULL;
else
{
(trim-> refs)++;
return trim;
}
}
void trim_rotate_cp (DBL angle,DBL *up,DBL *vp,int num)
{
DBL s,c, x,y;
angle*= M_PI_180;
s= sin(angle);
c= cos(angle);
for (; num; num--, up++, vp++)
{
x= *up;
y= *vp;
*up= x * c - y * s;
*vp= x * s + y * c;
}
}
void trim_scale_cp ( DBL *vec,DBL *up,DBL *vp,int num)
{
for (; num; num--, up++, vp++)
{
*up *= vec[0];
*vp *= vec[1];
}
}
void trim_translate_cp ( DBL *vec,DBL *up,DBL *vp,int num)
{
for (; num; num--, up++, vp++)
{
*up += vec[0];
*vp += vec[1];
}
}
void trim_compute_bounds (TRIM_SHAPE *trim)
{
int tmp;
DBL *u,*v;
trim->bounds[0][0]=trim->bounds[0][1]= trim-> u[0];
trim->bounds[1][0]=trim->bounds[1][1]= trim->v[0];
u= trim->u;
v= trim->v;
for (tmp=1; tmp < trim->num_of_cp; tmp++)
{
if (trim->bounds[0][0] > u[tmp]) trim->bounds[0][0]= u[tmp];
if (trim->bounds[0][1] < u[tmp]) trim->bounds[0][1]= u[tmp];
if (trim->bounds[1][0] > v[tmp]) trim->bounds[1][0]= v[tmp];
if (trim->bounds[1][1] < v[tmp]) trim->bounds[1][1]= v[tmp];
}
}
TRIM_SHAPE *trim_deep_copy( TRIM_SHAPE *trim)
{
char *b;
int len;
TRIM_SHAPE *New;
New= (TRIM_SHAPE *) POV_MALLOC (sizeof(TRIM_SHAPE), "trimming shape");
memcpy( New, trim, sizeof(TRIM_SHAPE));
b= (char *) trim -> u;
len= (trim->ctypes - b);
len+= trim->num_of_parts;
New-> u= (DBL *) POV_MALLOC ( len, "trimming shape");
memcpy (New->u, trim->u, len );
/* what a horrible adress arithmetic */
New-> v= New->u + ((trim->v) - (trim->u));
New-> w= New->u + ((trim->w) - (trim->u));
New-> ctypes= (char *) New->u;
New-> ctypes+= (trim->ctypes - b);
New-> refs= 1;
return New;
} /* End of really ugly function */
#else
static char dummy[2];
#endif /*#ifdef RBezierPatch */