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