axis.c

Go to the documentation of this file.
00001 /*                          A X I S . 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 axis */
00021 /** @{ */
00022 /** @file libbn/axis.c
00023  *
00024  * @brief
00025  *      This routine is used to generate an axis for a graph.
00026  * It draws an axis with a linear scale, places tic marks every inch,
00027  * labels the tics, and uses the supplied title for the axis.
00028  *
00029  *      The strategy behind this routine is to split the axis
00030  * into SEGMENTS, which run from one tick to the next.  The
00031  * origin of the first segment (x, y), the origin of the bottom
00032  * of the first tick (xbott, ybott), and the origin of the first
00033  * tick label (xnum, ynum) are computed along with the delta x
00034  * and delta y (xincr, yincr) which describes the interval to
00035  * the start of the next tick.
00036  *
00037  * Originally written on August 01, 1978
00038  *
00039  */
00040 /** @} */
00041 
00042 #include "common.h"
00043 
00044 #include <stdio.h>
00045 #include <math.h>
00046 #include <string.h>
00047 
00048 #include "vmath.h"
00049 #include "plot3.h"
00050 
00051 #define TICK_YLEN       (char_width)    /**< @brief tick is 1 character height */
00052 #define NUM_YOFF        (3*char_width)  /**< @brief numbers offset from line */
00053 #define TITLE_YOFF      (5*char_width)  /**< @brief title offset from line */
00054 
00055 void
00056 tp_3axis(FILE *fp,              /**< output file */
00057          char *string,          /**< label for axis */
00058          fastf_t *origin,       /**< simple 3d point */
00059          fastf_t *rot,          /**< rotation angle */
00060          double length,         /**< length of axis */
00061          int ccw,               /**< 0=clockwise, !0=counter clockwise (ccw) */
00062          int ndigits,           /**< # digits wide */
00063          double label_start,    /**< label starting value */
00064          double label_incr,     /**< label increment between ticks */
00065          double tick_separation, /**< plot distance between ticks */
00066          double char_width)     /**< character scale (size) */
00067 {
00068     register int i;
00069     int nticks;
00070     point_t     tick_bottom;                    /* -Y point of tick */
00071     vect_t      axis_incr;                      /* +X vect between ticks */
00072     vect_t      axis_dir;
00073     point_t     title_left;                     /* left edge of title */
00074     point_t     cur_point;
00075     point_t     num_start;
00076     point_t     num_center;                     /* center point of number */
00077     point_t     num_last_end;                   /* end of last number */
00078     vect_t      temp;
00079     vect_t      diff;
00080     mat_t       xlate_to_0;
00081     mat_t       mat;                            /* combined transform */
00082     char        fmt[32];
00083     char        str[64];
00084 
00085     /* Determine direction for ticks */
00086     if (ccw)
00087         ccw = -1;                       /* counter clockwise */
00088     else
00089         ccw = 1;                        /* clockwise */
00090 
00091     if (ZERO(tick_separation)) tick_separation = 1;
00092 
00093     /*
00094      *  The point "origin" will be the center of the axis rotation.
00095      *  On the assumption that this origin point is not at (0, 0, 0),
00096      *  translate origin to (0, 0, 0) & apply the provided rotation matrix.
00097      *  If the user provides translation or
00098      *  scaling in his matrix, it will also be applied, but in most
00099      *  cases that would not be useful.
00100      */
00101     MAT_IDN(xlate_to_0);
00102     MAT_DELTAS_VEC(xlate_to_0, origin);
00103     bn_mat_mul(mat, rot, xlate_to_0);
00104     VMOVE(cur_point, origin);
00105 
00106     /* Compute the bottom of the first tick */
00107     VSET(temp, 0, -TICK_YLEN * ccw, 0);
00108     MAT4X3PNT(tick_bottom, mat, temp);
00109 
00110     /* Compute the start of this tick's label */
00111     VSET(temp, 0, -NUM_YOFF * ccw, 0);
00112     MAT4X3PNT(num_center, mat, temp);
00113     temp[X] = -char_width*ndigits;
00114     MAT4X3PNT(num_last_end, mat, temp);
00115 
00116     /* Determine the increment between ticks */
00117     VSET(temp, 1, 0, 0);
00118     MAT4X3VEC(axis_dir, mat, temp);
00119     VSCALE(axis_incr, axis_dir, tick_separation);
00120 
00121     /* Center the title, and find left edge */
00122     VSET(temp, 0.5*(length - strlen(string)*char_width), -TITLE_YOFF*ccw, 0);
00123     MAT4X3PNT(title_left, mat, temp);
00124     tp_3symbol(fp, string, title_left, rot, char_width);
00125 
00126     nticks = length/tick_separation+0.5;
00127     pdv_3move(fp, cur_point);
00128     for (i=0; i<=nticks; i++) {
00129         /*
00130          *  First, draw a tick.
00131          *  Then, if room, draw a numeric label.
00132          *  If last tick, done.
00133          *  Otherwise, advance in axis_dir direction.
00134          */
00135         pdv_3cont(fp, tick_bottom);
00136 
00137         if (ndigits > 64) {
00138             bu_bomb("ERROR: Number of digits exceeds available buffer space");
00139         }
00140 
00141         if (ndigits > 0) {
00142             double f;
00143             snprintf(fmt, 32, "%%%dg", ndigits);
00144             snprintf(str, 64, fmt, label_start);
00145             f = strlen(str) * char_width * 0.5;
00146             VJOIN1(num_start, num_center, -f, axis_dir);
00147 
00148             /* Only label this tick if the number will not
00149              * overlap with the previous number.
00150              */
00151             VSUB2(diff, num_start, num_last_end);
00152             if (VDOT(diff, axis_dir) >= 0) {
00153                 tp_3symbol(fp, str, num_start, rot, char_width);
00154                 VJOIN1(num_last_end, num_center, f, axis_dir);
00155             }
00156         }
00157 
00158         if (i == nticks) break;
00159 
00160         /* Advance, and draw next axis segment */
00161         pdv_3move(fp, cur_point);
00162         VADD2(cur_point, cur_point, axis_incr);
00163         VADD2(tick_bottom, tick_bottom, axis_incr);
00164         VADD2(num_center, num_center, axis_incr);
00165 
00166         label_start += label_incr;
00167 
00168         pdv_3cont(fp, cur_point);               /* draw axis */
00169     }
00170 }
00171 
00172 
00173 void
00174 PL_FORTRAN(f3axis, F3AXIS)(FILE **fp,
00175                            char *string /**< label for axis */,
00176                            float *x, float *y, float *z /**< start coordinates for axis */,
00177                            float *length /**< length of axis */,
00178                            float *theta /**< rotation off X-axis, in degrees */,
00179                            int *ccw,
00180                            int *ndigits /**< # digits wide */,
00181                            float *label_start /**< minimum value on axis */,
00182                            float *label_incr /**< increment for each tick */,
00183                            float *tick_separation /**< distance between ticks */,
00184                            float *char_width /**< character scale (size) */)
00185 {
00186     char buf[128];
00187     mat_t mat;
00188     vect_t pnt;
00189 
00190     VSET(pnt, *x, *y, *z);
00191     MAT_IDN(mat);
00192     bn_mat_angles(mat, 0.0, 0.0, *theta);
00193     bu_strlcpy(buf, string, sizeof(buf));
00194 
00195     tp_3axis(*fp, buf, pnt, mat, *length, *ccw,
00196              *ndigits, *label_start, *label_incr,
00197              *tick_separation, *char_width);
00198 }
00199 /** @} */
00200 /*
00201  * Local Variables:
00202  * mode: C
00203  * tab-width: 8
00204  * indent-tabs-mode: t
00205  * c-file-style: "stroustrup"
00206  * End:
00207  * ex: shiftwidth=4 tabstop=8
00208  */
Generated on Tue Dec 11 13:14:27 2012 for LIBBN by  doxygen 1.6.3