//
//  GSGeometrieHelper.h
//
//  Created by Georg Seifert on 2009-12-01.
//  Copyright (c) 2009 schriftgestaltung.de. All rights reserved.
//

#import <Foundation/NSGeometry.h>
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>

typedef enum {
	GSTopLeft = 6,
	GSTopCenter = 7,
	GSTopRight = 8,
	GSCenterLeft = 3,
	GSCenterCenter = 4,
	GSCenterRight = 5,
	GSBottomLeft = 0,
	GSBottomCenter = 1,
	GSBottomRight = 2,
} GSAlignment;


typedef enum {
	ONTOP = 1,
	PARALLEL = 2
} GSIntersectionState;


#if defined(__LP64__) && __LP64__
#define	GSRound(Value)			lround(Value)
#else
#define	GSRound(Value)			(NSInteger)lroundf(Value)
#endif

#ifndef GSGeometrie_Helpers
#define GSGeometrie_Helpers

static inline NSPoint GSRoundPoint(NSPoint point){
	point.x = (CGFloat)round(point.x);
	point.y = (CGFloat)round(point.y);
	return point;
}
static inline NSSize GSRoundSize(NSSize size) {
	size.width = (CGFloat)round(size.width);
	size.height = (CGFloat)round(size.height);
	return size;
}
static inline NSPoint GSMaxPoint (NSPoint p1, NSPoint p2) {
	return NSMakePoint( (CGFloat)fmax( p1.x, p2.x ), (CGFloat)fmax( p1.y, p2.y ) );
}
static inline NSPoint GSMinPoint (NSPoint p1, NSPoint p2) {
	return NSMakePoint( (CGFloat)fmin( p1.x, p2.x ), (CGFloat)fmin( p1.y, p2.y ) );
}
static inline NSPoint GSScalePoint(NSPoint P, CGFloat scalar) {
	//UKLog(@"P: %@ scaler: %f", NSStringFromPoint(P), scalar);
	return NSMakePoint (P.x * scalar, P.y * scalar);
}

static inline NSPoint GSAddPoints(NSPoint P1, NSPoint P2) {
	return NSMakePoint (P1.x+P2.x, P1.y+P2.y);
}

static inline NSPoint GSSubtractPoints(NSPoint A, NSPoint B) {
	A.x -= B.x;
	A.y -= B.y;
	return A;
}
static inline CGFloat GSDistance(NSPoint A, NSPoint B) {
	return (CGFloat)hypot(A.x - B.x, A.y - B.y );
}

static inline NSRect GSScaleRect(NSRect rect, CGFloat scale) {
	rect.size.height *= scale;
	rect.size.width *= scale;
	return rect;
}
static inline NSSize GSScaleSize(NSSize aSize, CGFloat Scale) {
	aSize.width *= Scale;
	aSize.height *= Scale;
	return aSize;
	
}

#endif

CGFloat GSAngleOfVector(NSPoint P) ;
CGFloat GSAngleBetweenVectors(NSPoint firstPoint, NSPoint secondPoint ) ;


BOOL GSOffsetLine(NSPoint *P0, NSPoint *P1, CGFloat OffsetX, CGFloat OffsetY);

/*****
 *
 *   dot
 *
 *****/
CGFloat GSDot(NSPoint P1, NSPoint P2) ;

/*****
 *
 *   lerp
 *
 *****/
NSPoint GSLerp( NSPoint P1, NSPoint P2, CGFloat t);

NSPoint GSMiddlePoint( NSPoint P1, NSPoint P2);
/*****
 *
 *   gte - greater than or equal
 *
 *****/
BOOL GSGte ( NSPoint P1, NSPoint P2);

NSArray *GSIntersectBezier3Bezier3 (NSPoint a1, NSPoint a2, NSPoint a3, NSPoint a4, NSPoint b1, NSPoint b2, NSPoint b3, NSPoint b4) ;
NSArray *GSIntersectBezier3Line (NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4, NSPoint a1, NSPoint a2) ;
NSArray *GSIntersectBezier3LineTimes(NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4, NSPoint a1, NSPoint a2) ;
NSArray *GSIntersectBezier3LineUnlimited (NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4, NSPoint a1, NSPoint a2) ;
NSArray *GSIntersectBezier3LineUnlimitedTimes (NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4, NSPoint a1, NSPoint a2) ;

NSPoint GSIntersectLineLine (NSPoint a1, NSPoint a2, NSPoint b1, NSPoint b2) ;
NSPoint	GSIntersectLineLineUnlimited ( const NSPoint aa, const NSPoint ab, const NSPoint ba, const NSPoint bb );


CGFloat GSDistanceOfPointFromCurve( NSPoint inPoint, NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4 ) ;
CGFloat GSDistanceOfPointFromLineSegment( NSPoint inPoint, NSPoint a, NSPoint b ) ;
CGFloat GSDistanceOfPointFromLine( NSPoint inPoint, NSPoint a, NSPoint b ) ;

NSPoint GSNearestPointOnCurve(NSPoint inPoint, NSPoint p1, const NSPoint p2, const NSPoint p3, const NSPoint p4, CGFloat * t) ;
NSPoint GSNearestPointOnLineSegment( NSPoint inPoint, NSPoint a, NSPoint b, CGFloat * t ) ;
NSPoint GSNearestPointOnLine( NSPoint inPoint, NSPoint a, NSPoint b, CGFloat * t ) ;

/******
 *
 * Bezier dividing
 *
 ******/
void GSDividSegment(NSPoint P0, NSPoint P1, NSPoint P2, NSPoint P3, NSPoint *q0, NSPoint *q1, NSPoint *q2, NSPoint *q3, NSPoint *r1, NSPoint *r2, NSPoint *r3, CGFloat t);

NSPoint GSPointAtTime(NSPoint P0, NSPoint P1, NSPoint P2, NSPoint P3, CGFloat t) ;
CGFloat GSLengthOfSegment(NSPoint P0, NSPoint P1, NSPoint P2, NSPoint P3 );
CGFloat GSTForDistance(CGFloat Distance, NSPoint P0, NSPoint P1, NSPoint P2, NSPoint P3, CGFloat maxT ) ;

void GSExtremTimesOfBezier(NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4, CGFloat *t1, CGFloat *t2, CGFloat *t3, CGFloat *t4) ;
void GSExtremPointsOfBezier(NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4, NSPoint *r1, NSPoint *r2, NSPoint *r3, NSPoint *r4) ;
NSArray * GSExtremsOfBezier(NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4);
NSArray * GSComputeInflexion(NSPoint p1, NSPoint p2, NSPoint p3, NSPoint p4) ;
NSInteger GSPointSort(id value1, id value2, void *reverse) ;