
#import "BezierORShape.h"

#define NU 13
#define F .5522847 

static const float coeff[NU][2] = { 
    { 1, 0 }, { 1, F }, { F, 1 }, { 0, 1 }, {-F, 1 }, {-1, F }, 
    {-1, 0 }, {-1,-F }, {-F,-1 }, { 0,-1 }, { F,-1 }, { 1,-F }, { 1, 0} 
};

static const char eveEnd[] = "} ;\nendShape\n";

static void calculateMesh(const NSPoint *points,int npoints, RtPoint *mesh, RtBound boundingBox,
							float *r1,float *z1,float *r2,float *z2)
{
	int u, v;
	float a = 1.0,x,y;
	
	for(v = 0; v < npoints; v++){
		if(ABS(points[v].x) > a)
			a = ABS(points[v].x);
		if(ABS(points[v].y) > a)
			a = ABS(points[v].y);
	}	
	boundingBox[0] = 1.0;
	boundingBox[1] = 1.0;
	boundingBox[2] = 1.0;
	boundingBox[3] = 1.0;
	boundingBox[4] = 1.0;
	boundingBox[5] = 1.0;
    	for(v = 0; v < npoints; v++){ 
		x = points[v].x / a;
		y = points[v].y / a; 
        for(u = 0; u < NU; u++){    
            mesh[v * NU + u][0] = x * coeff[u][0];
            mesh[v * NU + u][1] = x * coeff[u][1];
            mesh[v * NU + u][2] = y;
        }
		if(x > boundingBox[1]){
			boundingBox[0] = -x;
			boundingBox[1] = x;
			boundingBox[2] = -x;
			boundingBox[3] = x;
		}
		if(y > boundingBox[5]){
			boundingBox[5] = y;
			*r1 = x;
			*z1 = y;
		}
		if(y < boundingBox[4]){
			boundingBox[4] = y;
			*r2 = x;
			*z2 = y;
		}
	}
}


@implementation BezierORShape

+ shapeWithPoints:(const NSPoint *)thePoints :(int)theN
{
	return [[[self alloc] initWithPoints:thePoints :theN] autorelease];
}

- initWithPoints:(const NSPoint *)thePoints :(int)theN
{
	[super init];
	mesh = NSZoneMalloc([self zone], sizeof(RtPoint) * theN * NU);
	calculateMesh(thePoints, theN, mesh, boundingBox,&r1,&z1,&r2,&z2);
	numberOfPoints = theN;
	return self;
}

- (void)dealloc
{
	NSZoneFree([self zone],mesh);
	return [super dealloc];
}
	

- (NSData *)eveData
{
	char buffer[500];
	int u,v;
	NSMutableData *resultData;
	
	sprintf(buffer,"\tPatchMesh bicubic %d nonperiodic %d nonperiodic {P} { \n", NU, numberOfPoints);
	resultData = [NSMutableData dataWithBytes:buffer length:strlen(buffer)];
	for(v = 0; v < numberOfPoints; v++) 
        	for(u = 0; u < NU; u++){  
			sprintf(buffer,"\t\t%f %f %f\n", mesh[v * NU + u][0], mesh[v * NU + u][1],mesh[v * NU + u][2]);
			[resultData appendBytes:buffer length:strlen(buffer)];
        	}
	[resultData appendBytes:eveEnd length:strlen(eveEnd)];
	return resultData;
}

@end
  
