123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- #include "gd.h"
- #include <math.h>
- #ifndef M_PI
- # define M_PI 3.14159265358979323846
- #endif
- /**
- * Title: Matrix
- * Group: Affine Matrix
- */
- /**
- * Function: gdAffineApplyToPointF
- * Applies an affine transformation to a point (floating point
- * gdPointF)
- *
- *
- * Parameters:
- * dst - Where to store the resulting point
- * affine - Source Point
- * flip_horz - affine matrix
- *
- * Returns:
- * GD_TRUE if the affine is rectilinear or GD_FALSE
- */
- int gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src,
- const double affine[6])
- {
- double x = src->x;
- double y = src->y;
- dst->x = x * affine[0] + y * affine[2] + affine[4];
- dst->y = x * affine[1] + y * affine[3] + affine[5];
- return GD_TRUE;
- }
- /**
- * Function: gdAffineInvert
- * Find the inverse of an affine transformation.
- *
- * All non-degenerate affine transforms are invertible. Applying the
- * inverted matrix will restore the original values. Multiplying <src>
- * by <dst> (commutative) will return the identity affine (rounding
- * error possible).
- *
- * Parameters:
- * dst - Where to store the resulting affine transform
- * src_affine - Original affine matrix
- * flip_horz - Whether or not to flip horizontally
- * flip_vert - Whether or not to flip vertically
- *
- * See also:
- * <gdAffineIdentity>
- *
- * Returns:
- * GD_TRUE on success or GD_FALSE on failure
- */
- int gdAffineInvert (double dst[6], const double src[6])
- {
- double r_det = (src[0] * src[3] - src[1] * src[2]);
- if (r_det <= 0.0) {
- return GD_FALSE;
- }
- r_det = 1.0 / r_det;
- dst[0] = src[3] * r_det;
- dst[1] = -src[1] * r_det;
- dst[2] = -src[2] * r_det;
- dst[3] = src[0] * r_det;
- dst[4] = -src[4] * dst[0] - src[5] * dst[2];
- dst[5] = -src[4] * dst[1] - src[5] * dst[3];
- return GD_TRUE;
- }
- /**
- * Function: gdAffineFlip
- * Flip an affine transformation horizontally or vertically.
- *
- * Flips the affine transform, giving GD_FALSE for <flip_horz> and
- * <flip_vert> will clone the affine matrix. GD_TRUE for both will
- * copy a 180° rotation.
- *
- * Parameters:
- * dst - Where to store the resulting affine transform
- * src_affine - Original affine matrix
- * flip_h - Whether or not to flip horizontally
- * flip_v - Whether or not to flip vertically
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineFlip (double dst[6], const double src[6], const int flip_h, const int flip_v)
- {
- dst[0] = flip_h ? - src[0] : src[0];
- dst[1] = flip_h ? - src[1] : src[1];
- dst[2] = flip_v ? - src[2] : src[2];
- dst[3] = flip_v ? - src[3] : src[3];
- dst[4] = flip_h ? - src[4] : src[4];
- dst[5] = flip_v ? - src[5] : src[5];
- return GD_TRUE;
- }
- /**
- * Function: gdAffineConcat
- * Concat (Multiply) two affine transformation matrices.
- *
- * Concats two affine transforms together, i.e. the result
- * will be the equivalent of doing first the transformation m1 and then
- * m2. All parameters can be the same matrix (safe to call using
- * the same array for all three arguments).
- *
- * Parameters:
- * dst - Where to store the resulting affine transform
- * m1 - First affine matrix
- * m2 - Second affine matrix
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineConcat (double dst[6], const double m1[6], const double m2[6])
- {
- double dst0, dst1, dst2, dst3, dst4, dst5;
- dst0 = m1[0] * m2[0] + m1[1] * m2[2];
- dst1 = m1[0] * m2[1] + m1[1] * m2[3];
- dst2 = m1[2] * m2[0] + m1[3] * m2[2];
- dst3 = m1[2] * m2[1] + m1[3] * m2[3];
- dst4 = m1[4] * m2[0] + m1[5] * m2[2] + m2[4];
- dst5 = m1[4] * m2[1] + m1[5] * m2[3] + m2[5];
- dst[0] = dst0;
- dst[1] = dst1;
- dst[2] = dst2;
- dst[3] = dst3;
- dst[4] = dst4;
- dst[5] = dst5;
- return GD_TRUE;
- }
- /**
- * Function: gdAffineIdentity
- * Set up the identity matrix.
- *
- * Parameters:
- * dst - Where to store the resulting affine transform
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineIdentity (double dst[6])
- {
- dst[0] = 1;
- dst[1] = 0;
- dst[2] = 0;
- dst[3] = 1;
- dst[4] = 0;
- dst[5] = 0;
- return GD_TRUE;
- }
- /**
- * Function: gdAffineScale
- * Set up a scaling matrix.
- *
- * Parameters:
- * scale_x - X scale factor
- * scale_y - Y scale factor
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineScale (double dst[6], const double scale_x, const double scale_y)
- {
- dst[0] = scale_x;
- dst[1] = 0;
- dst[2] = 0;
- dst[3] = scale_y;
- dst[4] = 0;
- dst[5] = 0;
- return GD_TRUE;
- }
- /**
- * Function: gdAffineRotate
- * Set up a rotation affine transform.
- *
- * Like the other angle in libGD, in which increasing y moves
- * downward, this is a counterclockwise rotation.
- *
- * Parameters:
- * dst - Where to store the resulting affine transform
- * angle - Rotation angle in degrees
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineRotate (double dst[6], const double angle)
- {
- const double sin_t = sin (angle * M_PI / 180.0);
- const double cos_t = cos (angle * M_PI / 180.0);
- dst[0] = cos_t;
- dst[1] = sin_t;
- dst[2] = -sin_t;
- dst[3] = cos_t;
- dst[4] = 0;
- dst[5] = 0;
- return GD_TRUE;
- }
- /**
- * Function: gdAffineShearHorizontal
- * Set up a horizontal shearing matrix || becomes \\.
- *
- * Parameters:
- * dst - Where to store the resulting affine transform
- * angle - Shear angle in degrees
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineShearHorizontal(double dst[6], const double angle)
- {
- dst[0] = 1;
- dst[1] = 0;
- dst[2] = tan(angle * M_PI / 180.0);
- dst[3] = 1;
- dst[4] = 0;
- dst[5] = 0;
- return GD_TRUE;
- }
- /**
- * Function: gdAffineShearVertical
- * Set up a vertical shearing matrix, columns are untouched.
- *
- * Parameters:
- * dst - Where to store the resulting affine transform
- * angle - Shear angle in degrees
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineShearVertical(double dst[6], const double angle)
- {
- dst[0] = 1;
- dst[1] = tan(angle * M_PI / 180.0);
- dst[2] = 0;
- dst[3] = 1;
- dst[4] = 0;
- dst[5] = 0;
- return GD_TRUE;
- }
- /**
- * Function: gdAffineTranslate
- * Set up a translation matrix.
- *
- * Parameters:
- * dst - Where to store the resulting affine transform
- * offset_x - Horizontal translation amount
- * offset_y - Vertical translation amount
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineTranslate (double dst[6], const double offset_x, const double offset_y)
- {
- dst[0] = 1;
- dst[1] = 0;
- dst[2] = 0;
- dst[3] = 1;
- dst[4] = offset_x;
- dst[5] = offset_y;
- return GD_TRUE;
- }
- /**
- * gdAffineexpansion: Find the affine's expansion factor.
- * @src: The affine transformation.
- *
- * Finds the expansion factor, i.e. the square root of the factor
- * by which the affine transform affects area. In an affine transform
- * composed of scaling, rotation, shearing, and translation, returns
- * the amount of scaling.
- *
- * GD_SUCCESS on success or GD_FAILURE
- **/
- double gdAffineExpansion (const double src[6])
- {
- return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
- }
- /**
- * Function: gdAffineRectilinear
- * Determines whether the affine transformation is axis aligned. A
- * tolerance has been implemented using GD_EPSILON.
- *
- * Parameters:
- * m - The affine transformation
- *
- * Returns:
- * GD_TRUE if the affine is rectilinear or GD_FALSE
- */
- int gdAffineRectilinear (const double m[6])
- {
- return ((fabs (m[1]) < GD_EPSILON && fabs (m[2]) < GD_EPSILON) ||
- (fabs (m[0]) < GD_EPSILON && fabs (m[3]) < GD_EPSILON));
- }
- /**
- * Function: gdAffineEqual
- * Determines whether two affine transformations are equal. A tolerance
- * has been implemented using GD_EPSILON.
- *
- * Parameters:
- * m1 - The first affine transformation
- * m2 - The first affine transformation
- *
- * Returns:
- * GD_SUCCESS on success or GD_FAILURE
- */
- int gdAffineEqual (const double m1[6], const double m2[6])
- {
- return (fabs (m1[0] - m2[0]) < GD_EPSILON &&
- fabs (m1[1] - m2[1]) < GD_EPSILON &&
- fabs (m1[2] - m2[2]) < GD_EPSILON &&
- fabs (m1[3] - m2[3]) < GD_EPSILON &&
- fabs (m1[4] - m2[4]) < GD_EPSILON &&
- fabs (m1[5] - m2[5]) < GD_EPSILON);
- }
|