/*
  *** DO NOT EDIT ***
  This file has been generated by opc89, and will be overwritten.
  Please edit the source of this file instead.
*/

#ifndef G2D_XFORM_H
#define G2D_XFORM_H
#include <opc89.h>
#include <gengeo2d/prim.h>
#include <gengeo2d/common.h>
#include <gengeo2d/vect.h>


/****** API ******/
G2D_INLINE g2d_cvect_t g2d_xform_cvect(g2d_xform_t mx, g2d_cvect_t vect);
G2D_INLINE g2d_cvect_t g2d_xform_vect(g2d_xform_t mx, g2d_vect_t vect);
G2D_INLINE g2d_vect_t g2d_xform_vect2vect(g2d_xform_t mx, g2d_vect_t vect);


/****** IMPLEMENTATION ******/

G2D_INLINE g2d_cvect_t g2d_xform_cvect(g2d_xform_t mx, g2d_cvect_t vect)
{
	return g2d_cvect(
		g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(vect.x  ,mx.v[0] ) ,g2d_calc_t_mul_g2d_calc_t(vect.y  ,mx.v[1] ) ),mx.v[2]),
		g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(vect.x  ,mx.v[3] ) ,g2d_calc_t_mul_g2d_calc_t(vect.y  ,mx.v[4] ) ),mx.v[5]
)	);
}

G2D_INLINE g2d_cvect_t g2d_xform_vect(g2d_xform_t mx, g2d_vect_t vect)
{
	return g2d_cvect(
		g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(g2d_calc_t_convfrom_g2d_coord_t(vect.x ) ,mx.v[0] ) ,g2d_calc_t_mul_g2d_calc_t(g2d_calc_t_convfrom_g2d_coord_t(vect.y ) ,mx.v[1] ) ),mx.v[2]),
		g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(g2d_calc_t_convfrom_g2d_coord_t(vect.x ) ,mx.v[3] ) ,g2d_calc_t_mul_g2d_calc_t(g2d_calc_t_convfrom_g2d_coord_t(vect.y ) ,mx.v[4] ) ),mx.v[5]
)	);
}

G2D_INLINE g2d_vect_t g2d_xform_vect2vect(g2d_xform_t mx, g2d_vect_t vect)
{
	return g2d_vect(
		g2d_coord_t_convfrom_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(g2d_calc_t_convfrom_g2d_coord_t(vect.x ) ,mx.v[0] ) ,g2d_calc_t_mul_g2d_calc_t(g2d_calc_t_convfrom_g2d_coord_t(vect.y ) ,mx.v[1] ) ),mx.v[2])),
		g2d_coord_t_convfrom_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(g2d_calc_t_convfrom_g2d_coord_t(vect.x ) ,mx.v[3] ) ,g2d_calc_t_mul_g2d_calc_t(g2d_calc_t_convfrom_g2d_coord_t(vect.y ) ,mx.v[4] ) ),mx.v[5]
)	));
}

G2D_INLINE g2d_xform_t g2d_xform_mult(const g2d_xform_t ma, const g2d_xform_t mb)
{
	g2d_xform_t res;

	res.v[0] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[0]  ,mb.v[0] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[1]  ,mb.v[3] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[2]  ,mb.v[6]));
	res.v[1] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[0]  ,mb.v[1] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[1]  ,mb.v[4] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[2]  ,mb.v[7]));
	res.v[2] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[0]  ,mb.v[2] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[1]  ,mb.v[5] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[2]  ,mb.v[8]));

	res.v[3] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[3]  ,mb.v[0] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[4]  ,mb.v[3] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[5]  ,mb.v[6]));
	res.v[4] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[3]  ,mb.v[1] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[4]  ,mb.v[4] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[5]  ,mb.v[7]));
	res.v[5] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[3]  ,mb.v[2] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[4]  ,mb.v[5] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[5]  ,mb.v[8]));

	res.v[6] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[6]  ,mb.v[0] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[7]  ,mb.v[3] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[8]  ,mb.v[6]));
	res.v[7] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[6]  ,mb.v[1] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[7]  ,mb.v[4] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[8]  ,mb.v[7]));
	res.v[8] = g2d_calc_t_add_g2d_calc_t(g2d_calc_t_add_g2d_calc_t(g2d_calc_t_mul_g2d_calc_t(ma.v[6]  ,mb.v[2] ) ,g2d_calc_t_mul_g2d_calc_t(ma.v[7]  ,mb.v[5] ) ),g2d_calc_t_mul_g2d_calc_t(ma.v[8]  ,mb.v[8]));

	return res;
}

G2D_INLINE g2d_xform_t g2d_xform_rotate(const g2d_xform_t mx, g2d_angle_t rad)
{
	g2d_xform_t tr;

	tr.v[0] = g2d_cos(rad);
	tr.v[1] = g2d_sin(rad);
	tr.v[2] = g2d_calc_t_convfrom_double(0.0);

	tr.v[3] = g2d_calc_t_neg(g2d_sin(rad));
	tr.v[4] = g2d_cos(rad);
	tr.v[5] = g2d_calc_t_convfrom_double(0.0);

	tr.v[6] = g2d_calc_t_convfrom_double(0.0);
	tr.v[7] = g2d_calc_t_convfrom_double(0.0);
	tr.v[8] = g2d_calc_t_convfrom_double(1.0);

	return g2d_xform_mult(mx, tr);
}

G2D_INLINE g2d_xform_t g2d_xform_translate(const g2d_xform_t mx, g2d_calc_t xt, g2d_calc_t yt)
{
	g2d_xform_t tr;

	tr.v[0] = g2d_calc_t_convfrom_double(1.0);
	tr.v[1] = g2d_calc_t_convfrom_double(0.0);
	tr.v[2] = xt;

	tr.v[3] = g2d_calc_t_convfrom_double(0.0);
	tr.v[4] = g2d_calc_t_convfrom_double(1.0);
	tr.v[5] = yt;

	tr.v[6] = g2d_calc_t_convfrom_double(0.0);
	tr.v[7] = g2d_calc_t_convfrom_double(0.0);
	tr.v[8] = g2d_calc_t_convfrom_double(1.0);

	return g2d_xform_mult(mx, tr);
}

G2D_INLINE g2d_xform_t g2d_xform_scale(const g2d_xform_t mx, g2d_calc_t sx, g2d_calc_t sy)
{
	g2d_xform_t tr;

	tr.v[0] = sx;
	tr.v[1] = g2d_calc_t_convfrom_double(0.0);
	tr.v[2] = g2d_calc_t_convfrom_double(0.0);

	tr.v[3] = g2d_calc_t_convfrom_double(0.0);
	tr.v[4] = sy;
	tr.v[5] = g2d_calc_t_convfrom_double(0.0);

	tr.v[6] = g2d_calc_t_convfrom_double(0.0);
	tr.v[7] = g2d_calc_t_convfrom_double(0.0);
	tr.v[8] = g2d_calc_t_convfrom_double(1.0);

	return g2d_xform_mult(mx, tr);
}

G2D_INLINE g2d_xform_t g2d_xform_shear(const g2d_xform_t mx, g2d_calc_t sx, g2d_calc_t sy)
{
	g2d_xform_t tr;

	tr.v[0] = g2d_calc_t_convfrom_double(1.0);
	tr.v[1] = sx;
	tr.v[2] = g2d_calc_t_convfrom_double(0.0);

	tr.v[3] = sy;
	tr.v[4] = g2d_calc_t_convfrom_double(1.0);
	tr.v[5] = g2d_calc_t_convfrom_double(0.0);

	tr.v[6] = g2d_calc_t_convfrom_double(0.0);
	tr.v[7] = g2d_calc_t_convfrom_double(0.0);
	tr.v[8] = g2d_calc_t_convfrom_double(1.0);

	return g2d_xform_mult(mx, tr);
}

G2D_INLINE g2d_xform_t g2d_xform_mirrorx(g2d_xform_t mx)
{
	return g2d_xform_scale(mx, g2d_calc_t_convfrom_double(1.0), g2d_calc_t_convfrom_double(-1.0));
}

G2D_INLINE g2d_xform_t g2d_xform_mirrory(g2d_xform_t mx)
{
	return g2d_xform_scale(mx, g2d_calc_t_convfrom_double(-1.0), g2d_calc_t_convfrom_double(1.0));
}
#endif /* G2D_XFORM_H */
