/* NSGeometry.c - geometry functions
   Copyright (C) 1993,1994 Free Software Foundation, Inc.

   Written by:  Adam Fedor <fedor@boulder.colorado.edu>
   Date: Mar 1995

   This file is part of the GNU Objective C Class Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <math.h>
#include <sys/param.h>
#include "MathArray/NSGeometry.h"

/* Create Basic Structures */
NSPoint	
NSMakePoint(float x, float y)
{
    NSPoint point;
    point.x = x;
    point.y = y;
    return point;
}

NSSize	
NSMakeSize(float w, float h)
{
    NSSize size;
    size.width  = w;
    size.height = h;
    return size;
}

NSRect	
NSMakeRect(float x, float y, float w, float h)
{
    NSRect rect;
    rect.origin.x = x;
    rect.origin.y = y;
    rect.size.width  = w;
    rect.size.height = h;
    return rect;
}

/* Get ractangle coordinates */
float 
NSMaxX(NSRect aRect)
{
    return aRect.origin.x + aRect.size.width;
}

float 
NSMaxY(NSRect aRect)
{
    return aRect.origin.y + aRect.size.height;
}

float 
NSMidX(NSRect aRect)
{
    return aRect.origin.x + aRect.size.width / 2.0;
}

float 
NSMidY(NSRect aRect)
{
    return aRect.origin.y + aRect.size.height / 2.0;
}

float 
NSMinX(NSRect aRect)
{
    return aRect.origin.x;
}

float 
NSMinY(NSRect aRect)
{
    return aRect.origin.y;
}

float 
NSWidth(NSRect aRect)
{
    return aRect.size.width;
}

float
NSHeight(NSRect aRect)
{
    return aRect.size.height;
}

/* Modify a copy of a rectangle */
NSRect 	
NSOffsetRect(NSRect aRect, float dx, float dy)
{
    NSRect rect = aRect;
    rect.origin.x += dx;
    rect.origin.y += dy;
    return rect;
}

NSRect 	
NSInsetRect(NSRect aRect, float dX, float dY)
{
    NSRect rect;
    rect = NSOffsetRect(aRect, dX, dY);
    rect.size.width -= (2*dX);
    rect.size.height -= (2*dY);
    return rect;
}

NSRect 	
NSIntegralRect(NSRect aRect)
{
    NSRect rect;
    if (NSIsEmptyRect(aRect)) {
    	return NSMakeRect(0, 0, 0, 0);
    }
	
    rect.origin.x = floor(aRect.origin.x);
    rect.origin.y = floor(aRect.origin.y);
    rect.size.width = ceil(aRect.size.width);
    rect.size.height = ceil(aRect.size.height);
    return rect;
}

void 	
NSDivideRect(NSRect aRect, NSRect *slice, NSRect *remainder,
			float amount, NSRectEdge edge)
{
    static NSRect sRect, rRect;
    
    if (!slice)
    	slice = &sRect;
    if (!remainder)
    	remainder = &rRect;
    
    if (NSIsEmptyRect(aRect)) {
    	*slice = NSMakeRect(0,0,0,0);
    	*remainder = NSMakeRect(0,0,0,0);
	return;
    }
    switch (edge) {
    case (NSMinXEdge):
    	if (amount > aRect.size.width) {
	    *slice = aRect;
	    *remainder = NSMakeRect(NSMaxX(aRect), aRect.origin.y, 
	    	 0, aRect.size.height);
	} else {
	    *slice = NSMakeRect(aRect.origin.x, aRect.origin.y, amount, 
		 aRect.size.height);
	    *remainder = NSMakeRect(NSMaxX(*slice), aRect.origin.y, 
	    	 NSMaxX(aRect)-NSMaxX(*slice), aRect.size.height);
	}
	break;
    case (NSMinYEdge):
    	if (amount > aRect.size.height) {
	    *slice = aRect;
	    *remainder = NSMakeRect(aRect.origin.x, NSMaxY(aRect), 
	    	      aRect.size.width, 0);
	} else {
	    *slice = NSMakeRect(aRect.origin.x, aRect.origin.y, 
		aRect.size.width, amount);
	    *remainder = NSMakeRect(aRect.origin.x, NSMaxY(*slice), 
	    	aRect.size.width, NSMaxY(aRect)-NSMaxY(*slice));
	}
	break;
    case (NSMaxXEdge):
    	if (amount > aRect.size.width) {
	    *slice = aRect;
	    *remainder = NSMakeRect(aRect.origin.x, aRect.origin.y, 
	    	 0, aRect.size.height);
	} else {
	    *slice = NSMakeRect(NSMaxX(aRect)-amount, aRect.origin.y,
	    	amount, aRect.size.height);
	    *remainder = NSMakeRect(aRect.origin.x, aRect.origin.y, 
	    	NSMinX(*slice)-aRect.origin.x, aRect.size.height);
	}
	break;
    case (NSMaxYEdge):
    	if (amount > aRect.size.height) {
	    *slice = aRect;
	    *remainder = NSMakeRect(aRect.origin.x, aRect.origin.y, 
	    	      aRect.size.width, 0);
	} else {
	    *slice = NSMakeRect(aRect.origin.x, NSMaxY(aRect)-amount, 
		aRect.size.width, amount);
	    *remainder = NSMakeRect(aRect.origin.x, aRect.origin.y, 
	    	aRect.size.width, NSMinY(*slice)-aRect.origin.y);
	}
	break;
    default:
	break;
    }
}

/* Compute a third rectangle from two rectangles */
NSRect 	
NSUnionRect(NSRect aRect, NSRect bRect)
{
    NSRect rect;
    if (NSIsEmptyRect(aRect) && NSIsEmptyRect(bRect))
    	return NSMakeRect(0,0,0,0);
    else if (NSIsEmptyRect(aRect)) 
    	return bRect;
    else if (NSIsEmptyRect(bRect))
    	return aRect;

    rect = NSMakeRect(MIN(NSMinX(aRect), NSMinX(bRect)), 
    		MIN(NSMinY(aRect), NSMinY(bRect)), 0, 0);
    rect = NSMakeRect(NSMinX(rect), NSMinY(rect),
    		MAX(NSMaxX(aRect), NSMaxX(bRect)) - NSMinX(rect),
    		MAX(NSMaxY(aRect), NSMaxY(bRect)) - NSMinY(rect));
    return rect;
}


/* Note that intersecting at a line or a point doesn't count */
BOOL     
NSIntersectsRect(NSRect aRect, NSRect bRect)
{
    return (NSMaxX(aRect) <= NSMinX(bRect) || \
	    NSMaxX(bRect) <= NSMinX(aRect) || \
	    NSMaxY(aRect) <= NSMinY(bRect) || \
	    NSMaxY(bRect) <= NSMinY(aRect)) ? NO : YES;
}

NSRect   
NSIntersectionRect (NSRect aRect, NSRect bRect)
{
    NSRect rect;
    if (!NSIntersectsRect(aRect, bRect)) {
	return NSMakeRect(0, 0, 0, 0);
    }
    if (NSMinX(aRect) <= NSMinX(bRect)) {
	rect.size.width = MIN(NSMaxX(aRect), NSMaxX(bRect)) - NSMinX(bRect);
	rect.origin.x = NSMinX(bRect);
    } else {
	rect.size.width = MIN(NSMaxX(aRect), NSMaxX(bRect)) - NSMinX(aRect);
	rect.origin.x = NSMinX(aRect);
    }
    if (NSMinY(aRect) <= NSMinY(bRect)) {
	rect.size.height = MIN(NSMaxY(aRect), NSMaxY(bRect)) - NSMinY(bRect);
	rect.origin.y = NSMinY(bRect);
    } else {
	rect.size.height = MIN(NSMaxY(aRect), NSMaxY(bRect)) - NSMinY(aRect);
	rect.origin.y = NSMinY(aRect);
    }
    return rect;
}


/* Test geometrical relationships */
BOOL 	
NSEqualRects(NSRect aRect, NSRect bRect)
{
    return ((NSMinX(aRect) == NSMinX(bRect)) 
    		&& (NSMinY(aRect) == NSMinY(bRect)) 
	    	&& (NSWidth(aRect) == NSWidth(bRect)) 
	    	&& (NSHeight(aRect) == NSHeight(bRect)));
}

BOOL 	
NSEqualSizes(NSSize aSize, NSSize bSize)
{
    return ((aSize.width == bSize.width) 
    		&& (aSize.height == bSize.height));
}

BOOL 	
NSEqualPoints(NSPoint aPoint, NSPoint bPoint)
{
    return ((aPoint.x == bPoint.x)
    		&& (aPoint.y == bPoint.y));
}

BOOL 	
NSIsEmptyRect(NSRect aRect)
{
    return (!((NSWidth(aRect) > 0) && (NSHeight(aRect) > 0)));
}

/* FIXME: what to do for flipped coordinates? */
BOOL 	
NSMouseInRect(NSPoint aPoint, NSRect aRect, BOOL flipped)
{
    return ((aPoint.x >= NSMinX(aRect))
	        && (aPoint.y >= NSMinY(aRect))
		&& (aPoint.x <= NSMaxX(aRect))
		&& (aPoint.y <= NSMaxY(aRect)));
}

BOOL 	
NSPointInRect(NSPoint aPoint, NSRect aRect)
{
    return NSMouseInRect(aPoint, aRect, YES);
}

BOOL 	
NSContainsRect(NSRect aRect, NSRect bRect)
{
    return ((NSMinX(aRect) < NSMinX(bRect)) &&
    	    (NSMinY(aRect) < NSMinY(bRect)) &&
	    (NSMaxX(aRect) > NSMaxX(bRect)) &&
	    (NSMaxY(aRect) > NSMaxY(bRect)));
}

