00001 /* S C A L E . C 00002 * BRL-CAD 00003 * 00004 * Copyright (c) 2004-2006 United States Government as represented by 00005 * the U.S. Army Research Laboratory. 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License 00009 * as published by the Free Software Foundation; either version 2 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, but 00013 * WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this file; see the file named COPYING for more 00019 * information. 00020 */ 00021 00022 /** \addtogroup plot */ 00023 /*@{*/ 00024 /** @file scale.c 00025 * @brief scale geometry points. 00026 * 00027 * 00028 * @author 00029 * Michael John Muuss 00030 * 00031 * @par Source 00032 * The U. S. Army Research Laboratory 00033 *@n Aberdeen Proving Ground, Maryland 21005-5068 USA 00034 * 00035 * @note 00036 * This file is a candidate for deletion. 00037 * Nothing else in BRL-CAD uses this. 00038 * 00039 */ 00040 00041 00042 #ifndef lint 00043 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbn/scale.c,v 14.10 2006/09/05 04:19:55 lbutler Exp $ (ARL)"; 00044 #endif 00045 00046 #include "common.h" 00047 00048 00049 00050 #include <stdio.h> 00051 #include <math.h> 00052 #include "machine.h" 00053 #include "vmath.h" 00054 #include "plot3.h" 00055 00056 /** 00057 * @brief 00058 * This routine is intended to take an array of 00059 * data points as input (either integer, floating, or 00060 * double), and scale it to fit in a space of LENGTH units. 00061 * 00062 * An output array is returned 00063 * which contains the scaled information stored in 16-bit integers. The input 00064 * and output arrays may overlap, as the input will never 00065 * occupy more space than the output. Also output are 00066 * the minimum value encountered (MIN), and a delta 00067 * factor showing the increase in value each XXXX. 00068 * This DX factor is rounded to 1,2,4,5,8,or 10 to 00069 * produce nicer looking axes. 00070 * 00071 * 00072 * @param[in] idata This pointer contains the address 00073 * of the input array to be scaled. 00074 * Actual type of array is determined 00075 * by MODE parameter. 00076 * 00077 * @param[in] elements Number of elements in IDATA to be used. 00078 * 00079 * @param[in] mode Specifies type of data that IDATA points 00080 * to; should be one of: 00081 * 'd' - double precision 00082 * 'f' - float (single precision) 00083 * 'i' - integer 00084 * 00085 * @param[in] length Contains the length (in 1/1000ths of an 00086 * inch) of the region in which the data is 00087 * to be scaled into. Note that the actual 00088 * amount of space needed may be this value 00089 * rounded up to the next inch. 00090 * 00091 * @param[out] odata This pointer contains the address of the 00092 * output array, which will always be of 00093 * integer type. 00094 * 00095 * @param[out] min This pointer contains the address of the 00096 * location for minimum point found to be 00097 * placed in. 00098 * 00099 * @param dx This pointer addresses the delta value 00100 * of the data which corresponds to the width 00101 * of EACH tick. 00102 * This implies that: 00103 * -# This is exactly the number to divide 00104 * raw data by to scale it to this scale 00105 * (ex: 2 graphs with one scale factor) 00106 * -# When this value is fed to the AXIS 00107 * routine, it must be multiplied 00108 * by 1000.0 first (to specify increment 00109 * between one INCH ticks). 00110 * 00111 * The fact that this routine returns variables of type DOUBLE has 00112 * important implications for FORTRAN users. These variables must 00113 * be declared of type DOUBLE PRECISION to reserve enough space. 00114 */ 00115 void 00116 tp_scale(int *idata, 00117 int elements, 00118 register int mode, 00119 int length, 00120 int *odata, 00121 double *min, 00122 double *dx) 00123 { 00124 double xmax, xmin, x, workdx; 00125 register int i; /* Index variable */ 00126 static double log_10; /* Saved value for log base-2(10) */ 00127 float *ifloatp; /* Used to convert pointer-to-int to float */ 00128 double *idoublep; /* Used to convert pointer-to-int to double */ 00129 double fractional; /* Fractional part of DX */ 00130 int integral; /* Integral part of DX */ 00131 00132 /* Prepare to use a pointer to an array of variable type */ 00133 ifloatp = (float *)idata; 00134 idoublep = (double *)idata; 00135 /* Find the maximum and minimum data values */ 00136 xmax = xmin = 0.0; 00137 for( i=0; i<elements; i++ ) { 00138 x = (mode=='f') 00139 ? ifloatp[i] 00140 : ( (mode=='d') 00141 ? idoublep[i] 00142 : idata[i] 00143 ); 00144 if( x > xmax ) 00145 xmax = x; 00146 if( x < xmin ) 00147 xmin = x; 00148 } 00149 00150 /* Split initial DX into integral and fractional exponents of 10 */ 00151 if( log_10 <= 0.0 ) 00152 log_10 = log(10.0); 00153 00154 fractional = log( (xmax-xmin)/length ) / log_10; /* LOG10(DX) */ 00155 integral = fractional; /* truncate! */ 00156 fractional -= integral; /* leave only fract */ 00157 00158 if( fractional < 0.0 ) { 00159 fractional += 1.0; /* ?? */ 00160 integral -= 1; 00161 } 00162 00163 fractional = pow( 10.0, fractional ); 00164 i = fractional - 0.01; 00165 switch( i ) { 00166 00167 case 1: 00168 fractional = 2.0; 00169 break; 00170 00171 case 2: 00172 case 3: 00173 fractional = 4.0; 00174 break; 00175 00176 case 4: 00177 fractional = 5.0; 00178 break; 00179 00180 case 5: 00181 case 6: 00182 case 7: 00183 fractional = 8.0; 00184 break; 00185 00186 case 8: 00187 case 9: 00188 fractional = 10.0; 00189 00190 } 00191 00192 /* Compute DX factor, combining power of ten & adjusted co-efficient */ 00193 workdx = pow( 10.0, (double)integral ) * fractional; 00194 00195 /* Apply the MIN and DX values to the users input data */ 00196 for( i=0; i<elements; i++ ) { 00197 if( mode == 'f' ) 00198 odata[i] = (ifloatp[i] - xmin) / workdx; 00199 else 00200 if( mode == 'd' ) 00201 odata[i] = (idoublep[i] - xmin) / workdx; 00202 else 00203 odata[i] = (idata[i] - xmin) / workdx; 00204 } 00205 00206 /* Send MIN and DX back to the user */ 00207 *min = xmin; 00208 *dx = workdx; 00209 } 00210 00211 00212 00213 /* 00214 * FORTRAN Interface 00215 */ 00216 void 00217 PL_FORTRAN(fscale, FSCALE)( idata, elements, mode, length, odata, min, dx ) 00218 int idata[]; 00219 int *elements; 00220 char *mode; 00221 int *length; 00222 int odata[]; 00223 double *min; 00224 double *dx; 00225 { 00226 tp_scale( idata, *elements, *mode, *length, odata, min, dx ); 00227 } 00228 00229 /*@}*/ 00230 /* 00231 * Local Variables: 00232 * mode: C 00233 * tab-width: 8 00234 * c-basic-offset: 4 00235 * indent-tabs-mode: t 00236 * End: 00237 * ex: shiftwidth=4 tabstop=8 00238 */