PLplot 5.9.6
|
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 }