//#  eulerN -- program for statistical estimation of Euler characteristic of a 3-dimensional body
//#  given as a sufficiently dense "volumetric" point sampling
//#
//#  Copyright (c) 2005-2007 Bradford Jones, Konstantin Rybnikov, Karen Daniels, Daniel Klain
//#  Release 2: 1 June 2007 
//#
//#  This program is free software; you can redistribute it and/or modify it
//#  under the terms of the GNU General Public License as published by the
//#  Free Software Foundation; either version 2, or (at your option) any
//#  later version: http://www.gnu.org/licenses/gpl.txt.
//#
//#  This program 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 General Public License for more details.
//#-----------------------------------------------------------------------------


#include "Interval.h"
/*--------------------------------------*/
/// constructors
/*--------------------------------------*/
Interval::Interval()
{
	upperBound = 0;
	lowerBound = 0;
}
Interval::Interval(double lower, double upper)
{
	// ensure that upperBound >= lowerBound
	if (lower <= upper)
	{
		lowerBound = lower;
		upperBound = upper;
	}
	else

	{
		lowerBound = upper;
		upperBound = lower;
	}
}
Interval::Interval(const Interval &i)
{
	upperBound = i.upperBound;
	lowerBound = i.lowerBound;
}

/*--------------------------------------*/
/// Member functions
/*--------------------------------------*/
void Interval::setUpper(double u)
{
	upperBound = u;
}
void Interval::setLower(double l)
{
	lowerBound = l;
}
double Interval::getUpper()
{

	return upperBound;
}
double Interval::getLower()
{
	return lowerBound;
}
double Interval::getLength()
{
	return (upperBound - lowerBound);
}
bool Interval::overlap (Interval &rhs)
{
	if ( (lowerBound <= rhs.getUpper() && lowerBound >= rhs.getLower()) || (upperBound <= rhs.getUpper() && upperBound >= rhs.getLower()) )
		return true;
	else if (upperBound >= rhs.getUpper() && lowerBound <= rhs.getLower())
		return true;
	else
		return false;
}
Interval Interval::intersection(Interval &rhs)
{
	Interval outputInterval = *this;

	//case 0: intervals are disjoint
	if (overlap(rhs) == false)
	{
		outputInterval.setUpper(0);
		outputInterval.setLower(0);
		return outputInterval;
	}

	//case 1: rhs is completely contained in interval
	if ( rhs.getUpper() <= upperBound && rhs.getLower() >= lowerBound)
		return rhs;

	// case2; rhs completely contains our interval
	if (rhs.getUpper() >= upperBound && rhs.getLower() <= lowerBound)
		return *this;

	//case3: partial overlap upwards
	if (rhs.getLower() >= lowerBound)
	{
		outputInterval.setUpper(upperBound);
		outputInterval.setLower(rhs.getLower());
		return outputInterval;
	}
	//case4: partial overlap downward
	else
	{
		outputInterval.setUpper(rhs.getUpper());
		outputInterval.setLower(lowerBound);
		return outputInterval;
	}
}

/*--------------------------------------*/
/// overloaded operators
/*--------------------------------------*/
Interval& Interval::operator = (const Interval &rhs)
{
	if (this == &rhs)
		return *this;

	upperBound = rhs.upperBound;
	lowerBound = rhs.lowerBound;

	return *this;
}

/*--------------------------------------*/
/// friend functions / binary operators
/*--------------------------------------*/
ostream& operator << (ostream &os, const Interval &i)
{
	os << '[' << i.lowerBound << ',' << i.upperBound << ']';
	return os;
}
