PLplot 5.9.6
plaffine.c
00001 /* $Id$
00002  *
00003  * Affine manipulation routines for PLplot.
00004  *
00005  * Copyright (C) 2009  Alan W. Irwin
00006  *
00007  * This file is part of PLplot.
00008  *
00009  * PLplot is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Library Public License as published
00011  * by the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * PLplot is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU Library General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Library General Public License
00020  * along with PLplot; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00022  *
00023  */
00024 
00025 #include "plplotP.h"
00026 
00027 /* For background on these affine functions see SVG specification, e.g.,
00028  * http://www.w3.org/TR/SVGTiny12/coords.html#EstablishingANewUserSpace.
00029  * Affine 3x3 matrices with elements A_i,j always have a last row of
00030  * 0, 0, 1 so the elements are conveniently stored in a vector in the order
00031  * A_1_1, A_2_1, A_1_2, A_2_2, A_1_3, A_2_3, with the last row implied.
00032  *
00033  * N.B.  The PLplot affine interpretation of translate, scale, etc., is
00034  * as actions on coordinate systems, rather than actions on objects.  This
00035  * is identical to the SVG specficiation interpretation.  However, the
00036  * SVG specification interprets the affine matrix as follows:
00037  * old_coord_vector = affine_matrix * new_coordinate vector.  In PLplot
00038  * we use the alternative interpretation
00039  * new_coord_vector = affine_matrix * old_coordinate vector.
00040  * The result is all affine matrices below are the inverses of the SVG
00041  * equivalents.
00042  *
00043  * N.B. All PLplot affine functions below return the affine matrix result (in
00044  * vector form) as the first argument).  It is the calling routine's
00045  * responsibility to provide the space for all affine matrix arguments,
00046  * i.e., a PLFLT array with a dimension of 6.
00047  *
00048  * /* Returns affine identity matrix */
00049 
00050 void
00051 plP_affine_identity( PLFLT *affine_vector )
00052 {
00053     affine_vector[0] = 1.;
00054     affine_vector[1] = 0.;
00055     affine_vector[2] = 0.;
00056     affine_vector[3] = 1.;
00057     affine_vector[4] = 0.;
00058     affine_vector[5] = 0.;
00059 }
00060 
00061 /* Translate new coordinate system axes relative to the old. */
00062 
00063 void
00064 plP_affine_translate( PLFLT *affine_vector, PLFLT xtranslate, PLFLT ytranslate )
00065 {
00066     affine_vector[0] = 1.;
00067     affine_vector[1] = 0.;
00068     affine_vector[2] = 0.;
00069     affine_vector[3] = 1.;
00070     /* If the new coordinate system axis is shifted by xtranslate and ytranslate
00071      * relative to the old, then the actual new coordinates are shifted in
00072      * the opposite direction. */
00073     affine_vector[4] = -xtranslate;
00074     affine_vector[5] = -ytranslate;
00075 }
00076 
00077 /* Scale new coordinate system axes relative to the old. */
00078 
00079 void
00080 plP_affine_scale( PLFLT *affine_vector, PLFLT xscale, PLFLT yscale )
00081 {
00082     /* If the new coordinate system axes are scaled by xscale and yscale
00083      * relative to the old, then the actual new coordinates are scaled
00084      * by the inverses. */
00085     if ( xscale == 0. )
00086     {
00087         plwarn( "plP_affine_scale: attempt to scale X coordinates by zero." );
00088         xscale = 1.;
00089     }
00090     if ( yscale == 0. )
00091     {
00092         plwarn( "plP_affine_scale: attempt to scale Y coordinates by zero." );
00093         yscale = 1.;
00094     }
00095     affine_vector[0] = 1. / xscale;
00096     affine_vector[1] = 0.;
00097     affine_vector[2] = 0.;
00098     affine_vector[3] = 1. / yscale;
00099     affine_vector[4] = 0.;
00100     affine_vector[5] = 0.;
00101 }
00102 
00103 /* Rotate new coordinate system axes relative to the old.
00104  * angle is in degrees.*/
00105 
00106 void
00107 plP_affine_rotate( PLFLT *affine_vector, PLFLT angle )
00108 {
00109     PLFLT cosangle = cos( PI * angle / 180. );
00110     PLFLT sinangle = sin( PI * angle / 180. );
00111     affine_vector[0] = cosangle;
00112     affine_vector[1] = -sinangle;
00113     affine_vector[2] = sinangle;
00114     affine_vector[3] = cosangle;
00115     affine_vector[4] = 0.;
00116     affine_vector[5] = 0.;
00117 }
00118 
00119 /* Skew new X coordinate axis relative to the old.
00120  * angle is in degrees.*/
00121 
00122 void
00123 plP_affine_xskew( PLFLT *affine_vector, PLFLT angle )
00124 {
00125     PLFLT tanangle = tan( PI * angle / 180. );
00126     affine_vector[0] = 1.;
00127     affine_vector[1] = 0.;
00128     affine_vector[2] = -tanangle;
00129     affine_vector[3] = 1.;
00130     affine_vector[4] = 0.;
00131     affine_vector[5] = 0.;
00132 }
00133 
00134 /* Skew new Y coordinate axis relative to the old.
00135  * angle is in degrees.*/
00136 
00137 void
00138 plP_affine_yskew( PLFLT *affine_vector, PLFLT angle )
00139 {
00140     PLFLT tanangle = tan( PI * angle / 180. );
00141     affine_vector[0] = 1.;
00142     affine_vector[1] = -tanangle;
00143     affine_vector[2] = 0.;
00144     affine_vector[3] = 1.;
00145     affine_vector[4] = 0.;
00146     affine_vector[5] = 0.;
00147 }
00148 
00149 /* Multiply two affine transformation matrices to form a third.
00150  *
00151  * A = B * C
00152  *
00153  */
00154 
00155 void
00156 plP_affine_multiply(
00157     PLFLT *affine_vectorA,
00158     const PLFLT *affine_vectorB,
00159     const PLFLT *affine_vectorC )
00160 {
00161     int   i;
00162     PLFLT result[NAFFINE];
00163     /* Multiply two affine matrices stored in affine vector form. */
00164     result[0] = affine_vectorB[0] * affine_vectorC[0] +
00165                 affine_vectorB[2] * affine_vectorC[1];
00166     result[2] = affine_vectorB[0] * affine_vectorC[2] +
00167                 affine_vectorB[2] * affine_vectorC[3];
00168     result[4] = affine_vectorB[0] * affine_vectorC[4] +
00169                 affine_vectorB[2] * affine_vectorC[5] +
00170                 affine_vectorB[4];
00171 
00172     result[1] = affine_vectorB[1] * affine_vectorC[0] +
00173                 affine_vectorB[3] * affine_vectorC[1];
00174     result[3] = affine_vectorB[1] * affine_vectorC[2] +
00175                 affine_vectorB[3] * affine_vectorC[3];
00176     result[5] = affine_vectorB[1] * affine_vectorC[4] +
00177                 affine_vectorB[3] * affine_vectorC[5] +
00178                 affine_vectorB[5];
00179 
00180     for ( i = 0; i < NAFFINE; i++ )
00181         affine_vectorA[i] = result[i];
00182 }
 All Data Structures Files Functions