import point2d;
import defines;
import globals;

// A class that steps on the ceiling of integers
// always steps on Y, rendering it useless for anything but polygon rasterization:
class CeilLine
{

	public long CEIL_FRACT;

	protected globals glob = new globals();

	protected long X1, X2, Y1, Y2;
	protected long X, StepX, StepZ, Z;
	protected long EdgeHeight, Y;
	
	//----------------------------------------------

	public CeilLine()
	{
		//XSTEP_PREC = 10;
		//ZSTEP_PREC = 26;
		CEIL_FRACT = ((1 << glob.XSTEP_PREC) -1);
		EdgeHeight = 0;
	} // CeilLine()

	//------------------------------------------------

	protected void Step()
	{
		// Step the edge:
		X+= StepX;
		Y++;
		Z+=StepZ;
		EdgeHeight--;
	}// Step()

	//------------------------------------------------

	protected void Step(long Amount)
	{
		// Step the edge by "Amount":
		X+= (StepX * Amount);
		Y+= Amount;
		Z+= (StepZ * Amount);
		EdgeHeight -= Amount;
	}// Step(long)

	//-------------------------------------------------

	public void Init(point2d P1, point2d P2)
	{
		// Calculate initial values for polygon edge:
		long FWidth, DeltaZ, Z1, Z2;
		X1 = P1.x;
		X2 = P2.x;
		Y1 = P1.y;
		Y2 = P2.y;
		Z1 = P1.z;
		Z2 = P2.z;

		EdgeHeight = (Y2 - Y1);
		FWidth = (X2 - X1) << glob.XSTEP_PREC;
		DeltaZ = (Z2 - Z1);

		X = (X1 << glob.XSTEP_PREC) + CEIL_FRACT;
		Y = Y1;
		Z = Z1+glob.ZTrans;

		if(EdgeHeight!= 0 )
		{
			StepX = FWidth / EdgeHeight;
			StepZ = DeltaZ / EdgeHeight;
		}
		else
		{
			StepX = 0;
			StepZ = 0;
		}

	}// Init()

	//----------------------------------------------

	public void ClipTop(int Top)
	{
		// Clip the polygon edge against the top of the viewport
		// Note: must be called directly after edge initialization

		double SlopeX;
		long Step, Height = Y2 - Y1;

		if((Y<Top) && (Height!=0))
		{
			Step = Top - Y;
			SlopeX = (double)(X2 - X1)/(double)Height;
			X = (X1 << glob.XSTEP_PREC) + ((long)(SlopeX * (double)Step) << glob.XSTEP_PREC)+
				CEIL_FRACT;
			Y = Top;
			Z += StepZ * Step;
			EdgeHeight -= Step;
		}

	}// ClipTop

	//-----------------------------------------------------------

	public void increment()
	{
		Step();
	} // increment

	//----------------------------------------------------------

	public void plusequal(long Amount)
	{
		Step(Amount);
	}// plusequal

	//-----------------------------------------------------------

	public point2d plus(long Amount)
	{
		// Return a point P + Amount
		point2d Temp = new point2d();
		Temp.x = X + (StepX * Amount);
		Temp.y = Y + (Amount);
		Temp.z = Z + (StepZ * Amount);
		return Temp;

	}// plus()

	//-----------------------------------------------------------

	public long GetX()
	{
		return (X >> glob.XSTEP_PREC);
	}// GetX()

	//-----------------------------------------------------------

	public long GetY()
	{
		return Y;
	}// GetY()

	//-----------------------------------------------------------

	public long GetZ()
	{
		return Z;
	}// GetZ()

	//-----------------------------------------------------------

	public long Height()
	{
		return EdgeHeight;
	}// Height()

};
