# AVSLib :: 'numeric' package :: 'curves2d' module
# Copyright (c) 2005 George Zarkadas (gzarkadas@users.sourceforge.net)

# 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 of the License, or (at your option) any later version.
# 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.
# You should have received a copy of the GNU General Public License along with this program; 
# if not, write to the "Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
# MA  02111-1307  USA"

DefineModule("avslib", "numeric", "curves2d")

# Calculates the corresponding y value of x so that (x, y) lies on 
# a straight line with slope 'slope' and intercept 'intercept'
#
Function Line(float x, float slope, float intercept)
{
	return slope * x + intercept
}

# Calculates the corresponding y value of x so that (x, y) lies on 
# a straight line with slope 'slope' passing by point (x1,y1)
#
Function Line1pt(float x, float x1, float y1, float slope)
{
	return y1 + (x - x1) * slope
}

# Calculates the corresponding y value of x so that (x, y) lies on 
# a straight line defined by end points (x1,y1) , (x2,y2)
#
Function Line2pt(float x, float x1, float y1, float x2, float y2)
{
	Assert(x1 != x2, "Line2pt: Division by zero (x1 == x2)")
	return y1 + (x - x1) * (y2 - y1) / (x2 - x1)
}

# Calculates the corresponding y value of x so that (x, y) lies on 
# a circle with radius 'radius' and (optionally; each value defaults to 0)
# with center (xc,yc).
# 'up_part' if true (default) makes the function to return the upper part 
# of the curve; if false the lower.
#
Function Circle(float x, float radius, bool "up_part", float "xc", float "yc")
{
	up_part = Default(up_part, true)
	xc = Default(xc, 0)
	yc = Default(yc, 0)
	Assert(radius > 0, \
		"Circle: 'radius' must be greater than zero")
	Assert(Abs(x - xc) <= radius, \
		"Circle: 'x' must be inside circle")
	sg = up_part ? 1 : -1
	return yc + sg * Sqrt(Pow(radius, 2) - Pow(x - xc, 2))
}

# Calculates the corresponding y value of x so that (x, y) lies on 
# an ellipsis with long axis half-length 'a' and short axis half-length 'b'
# and (optionally; each value defaults to 0) with center (xc,yc)
# 'up_part' if true (default) makes the function to return the upper part 
# of the curve; if false the lower.
#
Function Ellipsis(float x, float a, float b, bool "up_part", \
	float "xc", float "yc")
{
	up_part = Default(up_part, true)
	xc = Default(xc, 0)
	yc = Default(yc, 0)
	Assert(a > 0, \
		"Ellipsis: 'a' must be greater than zero")
	Assert(b > 0, \
		"Ellipsis: 'b' must be greater than zero")
	Assert(Abs(x - xc) <= a, \
		"Ellipsis: 'x' must be inside ellipsis")
	sg = up_part ? 1 : -1
	return yc + sg * Sqrt(Pow(b, 2) * (1 - Pow(x - xc, 2) / Pow(a, 2)))
}

# Calculates the corresponding y value of x so that (x, y) lies on 
# a parabola with axis parallel to x axis and with edge
# i.  located at distance 'a' from its focus 
# ii. (optionally; each value defaults to 0) placed at (xc,yc)
# 'up_part' if true (default) makes the function to return the upper part 
# of the curve; if false the lower.
# if x >= xc the function returns the y that corresponds to a parabola 
# opening towards the right x semi-axis; else the y that corresponds to a 
# parabola opening towards the left x semi-axis.
# Exchange x,y to get a parabola with axis parallel to y axis.
#
Function Parabola(float x, float a, bool "up_part", float "xc", float "yc")
{
	up_part = Default(up_part, true)
	xc = Default(xc, 0)
	yc = Default(yc, 0)
	Assert(a > 0, "Parabola: 'a' must be greater than zero")
	sg = up_part ? 1 : -1
	tr = x >= xc ? 1 : -1
	return yc + sg * Sqrt(tr * 4 * a * (x - xc))
}

# Calculates the corresponding y value of x so that (x, y) lies on 
# a hyperbola parallel to x axis, with long axis half-length 'a' and 
# short axis half-length 'b' and (optionally; each value defaults to 0) 
# with center (xc,yc)
# 'up_part' if true (default) makes the function to return the upper part 
# of the curve; if false the lower.
# if x >= xc + a the function returns the y that corresponds to the right 
# branch of the hyperbola; else the y that corresponds to the left branch.
# Exchange x,y to get a hyperbola with axis parallel to y axis.
#
Function Hyperbola(float x, float a, float b, bool "up_part", \
	float "xc", float "yc")
{
	up_part = Default(up_part, true)
	xc = Default(xc, 0)
	yc = Default(yc, 0)
	Assert(a > 0, \
		"Hyperbola: 'a' must be greater than zero")
	Assert(b > 0, \
		"Hyperbola: 'b' must be greater than zero")
	Assert(x <= xc - a || x >= xc + a, \
		"Hyperbola: 'x' must be inside hyperbola")
	sg = up_part ? 1 : -1
	return yc + sg * Sqrt(Pow(b, 2) * ((Pow(x - xc, 2) / Pow(a, 2)) - 1))
}
