#ifndef LTRANS_H
# define LTRANS_H

# ifndef GPK_STD_H
#  include <gpk_std.h>
# endif
# ifndef M22V2_H
#  include "m22v2.h"
# endif
# ifndef LINE_H
#  include "line.h"
# endif
// # include <iostream.h>
# ifndef TRANS_H
#  include "trans.h"
# endif

class box;

class ltransform : public transform	{
	matrix22 warp;
	vector2 shift;

	public:
	ltransform();
	~ltransform();
	ltransform(C box& from, C box& to);
	ltransform(C matrix22&w, C vector2& s);
	ltransform(C vector2& init_point, C vector2& final_point, C matrix22& warp);
	ltransform(C ltransform& a);
	ltransform& operator=(C ltransform& a);

	static ltransform identity(C vector_space *sfrom=0, C vector_space *sto=0);
	static ltransform translate(C vector2& s);

	BOOL ok() C;
	friend ostream& operator<<(ostream& s, C ltransform& t);
	C matrix22& Jacobian() C	{return warp;}
	double Wronskian() C	{return Jacobian().determinant();}
	vector2 inverse(C vector2& x) C;
	friend ltransform inverse(C ltransform& x);
	friend ltransform sqrt(C ltransform& x);
	vector2 operator()(C vector2&) C;
	line operator()(C line&) C;
	ltransform operator()(C ltransform&) C;
	vector2 Center() C	{return vector2(0,0,warp.in);}
	vector2 Shift() C	{return shift;}
	C matrix22& Warp() C	{return warp;}
	ltransform linearize() C	{return *this;}
	void set_in_space(C vector_space *i) { warp.in = i;}
	void set_out_space(C vector_space *o) { shift.set_space(o); warp.out=o;}
	};

ltransform sqrt(C ltransform& x);
inline ltransform operator*(C ltransform& x, C ltransform& y)
	{return x(y);}
ltransform inverse(C ltransform& x);
ostream& operator<<(ostream& s, C ltransform& t);

#endif
