/*	MiscCylinderShape.m

	Copyright 1996 Uwe Hoffmann.

	This notice may not be removed from this source code.
	The use and distribution of this software is governed by the
	terms of the MiscKit license agreement.  Refer to the license
	document included with the MiscKit distribution for the terms.

	Version 2 (August 1996)
*/

#import <Foundation/Foundation.h>
#import <AppKit/dpsOpenStep.h>
#import <AppKit/psops.h>

#import "MiscCylinderShape.h"
#import "MiscUserPath.h"
#import "MiscHitPath.h"
#import "MiscTDUtils.h"

@implementation MiscCylinderShape 

- (void)drawOutline
{
	int linejoin;
	
	PScurrentlinejoin(&linejoin);
	PSsetlinejoin(1);
	[super drawOutline];
	PSsetlinejoin(linejoin);
}


- (NSRect)innerBounds
{
	NSRect ir,b;
	
	b = [path1 bounds];
	ir.origin.x = b.origin.x;
	ir.origin.y = b.origin.y + b.size.height * 2 / 10;
	ir.size.width = b.size.width;
	ir.size.height = b.size.height * 6 / 10;
	return ir;
}

- (MiscShapeType)shapeType
{
	return MiscCylinderShapeType;
}

- (void)calcIntersection:(NSPoint *)ip angle:(float *)alpha toPoint:(NSPoint)aPoint
{
	NSPoint middle,l1,l2,pos;
	float s,width,height,*bbox,x0,y0,a,b;
	
	bbox = [path1 bbox];
	pos.x = bbox[0];
	pos.y = bbox[1];
	width = bbox[2] - bbox[0];
	height = bbox[3] - bbox[1];	
	middle.x = pos.x + width / 2;
	middle.y = pos.y + height / 2;
        if(aPoint.y == middle.y){
                 ip->y = middle.y;
                 if(aPoint.x > middle.x){
                         *alpha = 0;		
                         ip->x = pos.x + width;
                 } else {
                         *alpha = 180;		
                         ip->x = pos.x;
                 }
                 return;
         }
	if(aPoint.x == middle.x){
		ip->x = middle.x;
		if(aPoint.y > middle.y){
			ip->y = pos.y + height;
			*alpha = 90;
		} else {
			ip->y = pos.y;
			*alpha = -90;
		}
		return;
	}
	s = (aPoint.y - middle.y) / (aPoint.x - middle.x);
	*alpha = 57.29577951 * atan(s);
	if(aPoint.y > middle.y){
		if(aPoint.x > middle.x){ 						// I. quadrant
			l1.x = pos.x + width;
			l1.y = pos.y + height / 2;
                        l2.y = pos.y + height * 8 / 10;
			l2.x = pos.x + width;
			if(miscTD_straddles(l1, l2, middle, aPoint)){
                            	ip->x = l2.x;
                                ip->y = middle.y + s * (ip->x - middle.x);
			} else {
                            	x0 = middle.x;
                        	y0 = middle.y;
                        	a = width * 0.5455447256;
                       	 	b = height / 2;
                        	ip->x = a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + x0;
                        	ip->y = (2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
                        	if(ip->y < y0){
                                	ip->x = -(a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2))) + x0;
                                	ip->y = (-2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
                        	}
			}
		} else { 										// II. quadrant
                    	l1.x = pos.x;
                       	l1.y = pos.y + height / 2;
                       	l2.y = pos.y + height * 8 / 10;
                       	l2.x = pos.x;
                       	if(miscTD_straddles(l1, l2, middle, aPoint)){
                               ip->x = l2.x;
                               ip->y = middle.y + s * (ip->x - middle.x);
                       	} else {
                               x0 = middle.x;
                               y0 = middle.y;
                               a = width * 0.5455447256;
                               b = height / 2;
                               ip->x = a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + x0;
                               ip->y = (2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
                               if(ip->y < y0){
                                       ip->x = -(a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2))) + x0;
                                       ip->y = (-2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
                               }
                       	}
                        *alpha += 180;
		}
	} else {
		if(aPoint.x > middle.x){ 						// IV. quadrant
                    	l1.x = pos.x + width;
                       	l1.y = pos.y + height / 2;
                       	l2.y = pos.y + height * 2 / 10;
                       	l2.x = pos.x + width;
                       	if(miscTD_straddles(l1, l2, middle, aPoint)){
                              ip->x = l2.x;
                              ip->y = middle.y + s * (ip->x - middle.x);
                       	} else {
                              x0 = middle.x;
                              y0 = middle.y;
                              a = width * 0.5455447256;
                              b = height / 2;
                              ip->x = a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + x0;
                              ip->y = (2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
                              if(ip->y > y0){
                                      ip->x = -(a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2))) + x0;
                                      ip->y = (-2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
                              }
                       	}
		} else { 										// III. quadrant
                    	l1.x = pos.x;
                       	l1.y = pos.y + height / 2;
                       	l2.y = pos.y + height * 2 / 10;
                       	l2.x = pos.x;
                       	if(miscTD_straddles(l1, l2, middle, aPoint)){
                             ip->x = l2.x;
                             ip->y = middle.y + s * (ip->x - middle.x);
                       	} else {
                             x0 = middle.x;
                             y0 = middle.y;
                             a = width * 0.5455447256;
                             b = height / 2;
                             ip->x = a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + x0;
                             ip->y = (2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
                             if(ip->y > y0){
                                     ip->x = -(a*b/sqrt(pow(b,2) + pow(a,2)*pow(s,2))) + x0;
                                     ip->y = (-2*a*b*s/sqrt(pow(b,2) + pow(a,2)*pow(s,2)) + 2*y0)/2;
                             }
                       	}
                        *alpha += 180;
		}
	}
}


- (void)makePathWithBounds:(NSRect)aRect
{
	[path1 moveto:aRect.origin.x :aRect.origin.y + aRect.size.height * 2 / 10];
	[path1 curveto:aRect.origin.x :aRect.origin.y 
		:aRect.origin.x + aRect.size.width :aRect.origin.y
		:aRect.origin.x + aRect.size.width :aRect.origin.y + aRect.size.height * 2 / 10];
	[path1 rlineto:0.0 :aRect.size.height * 6 / 10];
	[path1 curveto:aRect.origin.x + aRect.size.width :aRect.origin.y + aRect.size.height
		:aRect.origin.x :aRect.origin.y + aRect.size.height
		:aRect.origin.x :aRect.origin.y + aRect.size.height * 8 / 10];
	[path1 closepath];
		
	[path2 moveto:aRect.origin.x :aRect.origin.y + aRect.size.height * 2 / 10];
	[path2 curveto:aRect.origin.x :aRect.origin.y
		:aRect.origin.x + aRect.size.width :aRect.origin.y
		:aRect.origin.x + aRect.size.width :aRect.origin.y + aRect.size.height * 2 / 10];
	[path2 curveto:aRect.origin.x + aRect.size.width :aRect.origin.y + aRect.size.height * 4 / 10
		:aRect.origin.x :aRect.origin.y + aRect.size.height * 4 / 10
		:aRect.origin.x :aRect.origin.y + aRect.size.height * 2 / 10];
	[path2 rlineto:0.0 :aRect.size.height * 6 / 10];
	[path2 curveto:aRect.origin.x :aRect.origin.y + aRect.size.height 
		:aRect.origin.x + aRect.size.width :aRect.origin.y + aRect.size.height
		:aRect.origin.x + aRect.size.width :aRect.origin.y + aRect.size.height * 8 / 10];	
	[path2 rlineto:0.0 :-aRect.size.height * 6 / 10];
	[path2 moveto:aRect.origin.x :aRect.origin.y + aRect.size.height * 2 / 10];
	[path2 closepath];
}
			
- (void)fillParamsWithBounds:(NSRect)aRect
{
	float *params, *bbox;
	
	params = [path1 params];
	bbox = [path1 bbox];
	bbox[0] = aRect.origin.x;
	bbox[1] = aRect.origin.y;
	bbox[2] = aRect.origin.x + aRect.size.width;
	bbox[3] = aRect.origin.y + aRect.size.height;	
	params[0] = aRect.origin.x;
	params[1] = aRect.origin.y + aRect.size.height * 2 / 10;	
	params[2] = aRect.origin.x;
	params[3] = aRect.origin.y;
	params[4] = aRect.origin.x + aRect.size.width;
	params[5] = aRect.origin.y;
	params[6] = aRect.origin.x + aRect.size.width;
	params[7] = aRect.origin.y + aRect.size.height * 2 / 10;	
	params[8] = 0.0;
	params[9] = aRect.size.height * 6 / 10;	
	params[10] = aRect.origin.x + aRect.size.width;
	params[11] = aRect.origin.y + aRect.size.height;
	params[12] = aRect.origin.x;
	params[13] = aRect.origin.y + aRect.size.height;
	params[14] = aRect.origin.x;
	params[15] = aRect.origin.y + aRect.size.height * 8 / 10;	
	
	params = [path2 params];
	bbox = [path2 bbox];
	bbox[0] = aRect.origin.x;
	bbox[1] = aRect.origin.y;
	bbox[2] = aRect.origin.x + aRect.size.width;
	bbox[3] = aRect.origin.y + aRect.size.height;	
	params[0] = aRect.origin.x;
	params[1] = aRect.origin.y + aRect.size.height * 2 / 10;	
	params[2] = aRect.origin.x;
	params[3] = aRect.origin.y;
	params[4] = aRect.origin.x + aRect.size.width;
	params[5] = aRect.origin.y;
	params[6] = aRect.origin.x + aRect.size.width;
	params[7] = aRect.origin.y + aRect.size.height * 2 / 10;	
	params[8] = aRect.origin.x + aRect.size.width;
	params[9] = aRect.origin.y + aRect.size.height * 4 / 10;
	params[10] = aRect.origin.x;
	params[11] = aRect.origin.y + aRect.size.height * 4 / 10;
	params[12] = aRect.origin.x;
	params[13] = aRect.origin.y + aRect.size.height * 2 / 10;	
	params[14] = 0.0;
	params[15] = aRect.size.height * 6 / 10;	
	params[16] = aRect.origin.x;
	params[17] = aRect.origin.y + aRect.size.height;
	params[18] = aRect.origin.x + aRect.size.width;
	params[19] = aRect.origin.y + aRect.size.height;
	params[20] = aRect.origin.x + aRect.size.width;
	params[21] = aRect.origin.y + aRect.size.height * 8 / 10;	
	params[22] = 0.0;
	params[23] = -aRect.size.height * 6 / 10;
	params[24] = aRect.origin.x;
	params[25] = aRect.origin.y + aRect.size.height * 2 / 10;
}

+ (NSSize)calcSizeForInnerSize:(NSSize)aSize
{
	NSSize os;
	
	os.width = aSize.width;
	os.height = aSize.height * 10 / 6;
	return os;
}
		              
@end


	
