Logo Search packages:      
Sourcecode: ygraph version File versions  Download package

util.c

Go to the documentation of this file.
/**
 * @file    util.c
 * @brief   Utility functions
 *
 *          A bunch of routines that manipulate strings and stuff.
 *
 * @author  Denis Pollney
 * @date    1 Oct 2001
 *
 * @par Copyright (C) 2001-2002 Denis Pollney
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 * @par
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details
 * @par
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <math.h>
#include <string.h>
#include <stdlib.h>

#include "ygraph.h"

/* The actual used font, only used as placeholder */
gchar* actual_font;

/**
 * @brief    Convert a double to a string.
 *
 * @param    val           A number.
 * @param    exp_notation  TRUE if the returned string should be in exponential
 *                         notation.
 * @returns  A string corresponding to the passed double.
 * @note     The string should be freed when it is no longer needed.
 */
inline gchar*
00046 double_to_str(gdouble val, gboolean exp_notation)
{
  gchar tmp_str[MAX_AXIS_LABEL_LENGTH];

  if (exp_notation)
    g_snprintf(tmp_str, MAX_AXIS_LABEL_LENGTH, "%4.3e%c", val, NULLC);
  else
    g_snprintf(tmp_str, MAX_AXIS_LABEL_LENGTH, "%4.3g%c", val, NULLC);
  return g_strdup(tmp_str);
}

/**
 * @brief    Convert a string to a double, noting that fortran output often
 *           will use 'd' or 'D' rather than 'e' to denote the exponent.
 *
 * @param    s  The string to be converted.
 * @returns  A double corresponding to the string.
 */
gdouble
00065 str_to_double(gchar* s)
{
  guint i;
  g_strdown(s);
  for (i=0; i<strlen(s); ++i)
    if (s[i]=='d') s[i] = 'e';
  return(g_strtod(s, NULL));
}

/**
 * @brief    Set the factor by which you need to multiply in order to convert
 *           xy to ij coordinates.
 *
 * @param    coord_range  A pointer to a pair of doubles which specify the
 *                        minimum and maximum data values respectively.
 * @param    window_size  The size (in pixels) of the window dimension in
 *                        question.
 * @returns  The multiplication factor required to convert a value to ij
 *           coordinates.
 */
inline gdouble
00086 set_fac(const gdouble x, const gdouble y, const gint window_size)
{
  g_assert (x<y);
  return window_size / (y - x);
}

/**
 * @brief    Convert x-axis coordinate values to i values.
 *
 * @param    plot  The plot.
 * @param    x     The coordinate value to be converted.
 * @returns  The i position (pixels) of the given data value.
 */
inline gint
00100 x_to_i(Plot* plot, gdouble x)
{
  gdouble i_fac;
  i_fac = set_fac(axis_transformation(plot->x_range[0], plot->x_axis),
                  axis_transformation(plot->x_range[1], plot->x_axis),
                  plot->i_size);
  return i_fac * (axis_transformation(x, plot->x_axis) -
                  axis_transformation(plot->x_range[0], plot->x_axis));
}

/**
 * @brief    Convert y-axis coordinate values to j values.
 *
 * @param    plot  The plot.
 * @param    y     The coordinate value to be converted.
 * @returns  The j position (pixels) of the given data value.
 */
inline gint
00118 y_to_j(Plot* plot, gdouble y)
{
  gdouble j_fac;
  j_fac = set_fac(axis_transformation(plot->y_range[0], plot->y_axis),
                  axis_transformation(plot->y_range[1], plot->y_axis),
                  plot->j_size);
  return -j_fac * (axis_transformation(y, plot->y_axis) -
                   axis_transformation(plot->y_range[0], plot->y_axis));
}

/**
 * @brief    Convert a plot window i-coordinate to a real x-coordinate value.
 *
 *           Values outside of the plot region are set to the appropriate 
 *           boundary of the range.
 *
 * @param    plot  The Plot.
 * @param    i     The i position (in pixels) of the point.
 * @returns  The coordinate value, along the x-axis, of the point.
 */
gdouble
00139 i_to_x(Plot* plot, gint i)
{
  gint i_pt;

  i_pt = MIN(i - plot->i_origin, plot->i_size);

  if (i_pt == plot->i_size)
    return plot->x_range[1];

  if (i_pt < 0)
    return plot->x_range[0];

  return plot->x_range[0]
    + (plot->x_range[1] - plot->x_range[0]) * i_pt/plot->i_size;
}

/**
 * @brief    Convert a plot window j-coordinate to a real y-coordinate value.
 *
 *           Values outside of the plot region are set to the appropriate
 *           boundary of the range.
 *
 * @param    plot  The Plot.
 * @param    j     The j position (in pixels) of the point.
 * @returns  The coordinate value, along the y-axis, of the point.
 */
gdouble
00166 j_to_y(Plot* plot, gint j)
{
  gint j_pt;

  j_pt = MIN(plot->j_origin - j, plot->j_size);

  if (j_pt == plot->j_size)
    return plot->y_range[1];

  if (j_pt < 0)
    return plot->y_range[0];

  return plot->y_range[0]
    + (plot->y_range[1] - plot->y_range[0]) *  j_pt/plot->j_size;
}

/**
 * @brief    Set the new x-axis ranges after a zoom.
 *
 * @param    plot  The Plot.
 * @param    i1    One i-coordinate of one end of the zoom box.
 * @param    i2    One i-coordinate of the other end of the zoom box.
 */
void
00190 zoom_x_range_set(Plot* plot, gint i1, gint i2)
{
  gint zoom_i_start;
  gint zoom_i_end;
  gdouble range[2];

  /*
   * Make sure that the zoom start and end points are not exactly the same.
   */
  if (i1 == i2)
    {
      zoom_i_start = i1;
      zoom_i_end = i1 + 1;
    }
  /*
   * Make sure that the order is right (start in upper-left, end lower right).
   */
  else if (i1 < i2)
    {
      zoom_i_start = i1;
      zoom_i_end = i2;
    }
  else
    {
      zoom_i_start = i2;
      zoom_i_end = i1;
    }

  range[0] = i_to_x(plot, zoom_i_start);
  range[1] = i_to_x(plot, zoom_i_end);
  
  if ((fabs(range[0]) > -G_MAXDOUBLE) && (range[1]>range[0]))
    {
      plot->x_range[0] = range[0];
      plot->x_range[1] = range[1];
    }
}

/**
 * @brief    Set the new y-axis ranges after a zoom.
 *
 * @param    plot  The Plot.
 * @param    i1    One i-coordinate of one end of the zoom box.
 * @param    i2    One i-coordinate of the other end of the zoom box.
 */
void
00236 zoom_y_range_set(Plot* plot, gint i1, gint i2)
{
  gint zoom_i_start;
  gint zoom_i_end;
  gdouble range[2];

  /*
   * Make sure that the zoom start and end points are not exactly the same.
   */
  if (i1 == i2)
    {
      zoom_i_start = i1;
      zoom_i_end = i1 - 1;
    }
  /*
   * Make sure that the order is right (start in upper-left, end lower right).
   */
  else if (i2 < i1)
    {
      zoom_i_start = i1;
      zoom_i_end = i2;
    }
  else
    {
      zoom_i_start = i2;
      zoom_i_end = i1;
    }

  range[0] = j_to_y(plot, zoom_i_start);
  range[1] = j_to_y(plot, zoom_i_end);

  if ((fabs(range[0]) > -G_MAXDOUBLE) && (range[1]>range[0]))
    {
      plot->y_range[0] = range[0];
      plot->y_range[1] = range[1];
    }
}

/**
 * @brief    Determine the frame of a data set which corresponds to a given 
 *           time.
 *
 *           The returned frame is the one with the smallest time >= the 
 *           global time as determined by the time of the global_current_frame.
 *
 * @param    data_set  The DataSet which is to be searched.
 * @returns  The frame index, within the DataSet, of the current frame.
 */
gint
00285 current_frame_calc(DataSet* data_set)
{
  gdouble cur_time;
  gint i;

  i=0;
  cur_time = g_array_index(global_time_list, gdouble, global_current_frame);
  while ((g_array_index(data_set->frame, Frame*, i)->time < cur_time)
         && (i < data_set->nframes))
    ++i;

  if (i == data_set->nframes)
    --i;

  return i;
}

/**
 * @brief    Get a DataSet by index from the global_data_set_list.
 *
 * @param    plot  The current Plot.
 * @param    idx   The index number of the requested data set.
 * @returns  The DataSet corresponding to the given index.
 */
DataSet*
00310 plot_get_data_index(Plot* plot, gint idx)
{
  return g_array_index(global_data_set_list, DataSet*, 
                       g_array_index(plot->data, gint, idx));
}

/**
 * @brief    Performs an 1D interpolation of the requested order, up to
 *           a hard-coded limit of MAX_INTERP_ORDER.
 *
 * @param    xy_data  An array of pointers to xy-pairs (doubles).
 * @param    x_val    The x coordinate value at which the data is to be
 *                    determined.
 * @param    order    The interpolation order.
 * @returns  The interpolated data value at the requested point.
 */
gdouble
00327 interp(GArray* xy_data, gdouble x_val, gint order)
{
  gdouble* right_pt;
  gdouble* left_pt;
  gdouble slope;
  guint right_idx;
  gint interp_order;

  if (order > MAX_INTERP_ORDER)
    {
      message_dialog
        ("Unsupported interpolation order. Resorting to linear interpolation");
      interp_order = 1;
    }
  else
    interp_order = order;

  if (interp_order == 1)
    {
      right_idx = 0;
      right_pt = g_array_index(xy_data, gdouble*, right_idx);

      while ((right_pt[0] < x_val) && (++right_idx < xy_data->len))
        right_pt = g_array_index(xy_data, gdouble*, right_idx);

      if (right_idx == 0)
        {
          right_idx = 1;
          right_pt = g_array_index(xy_data, gdouble*, right_idx);
        }

      left_pt = g_array_index(xy_data, gdouble*, right_idx-1);

      slope = (right_pt[1] - left_pt[1]) / (right_pt[0] - left_pt[0]);

      return (left_pt[1] + slope * (x_val - left_pt[0]));
    }
  else
    return 0;
}

/**
 * @brief    Convert a string to two columns.
 * 
 *           Strings of the form "x:y" are converted into a pair of
 *           ints.
 * @param    column_string  The string to be examined.
 * @returns  nothing
 */
00376 void string_to_columns(gchar* column_string)
{
  if ((sscanf(column_string, "%d:%d", &global_x_column, 
                                      &global_y_column)!=2) ||
      (global_x_column<1) || (global_y_column<1))
  {
    global_x_column=global_y_column=-1;
  }
  return;
}

void set_global_column_format_string()
{
  gint c;
  gchar *format, *tmp;

  /* build format string */
  if ((global_x_column==1) || (global_y_column==1))
    format=g_strdup("%s");
  else
    format=g_strdup("%*s");
  for (c=2; ((c<=global_x_column) || (c<=global_y_column)); c++)
  {
    if ((c==global_x_column) || (c==global_y_column))
    {
      tmp=format;
      format=g_strconcat(format, " %s", 0L);
      g_free(tmp);
    }
    else
    {
      tmp=format;
      format=g_strconcat(format, " %*s", 0L);
      g_free(tmp);
    }
  }
  global_column_format_string=g_strdup(format);
  g_free(format);
}

/**
 * @brief    Convert a string to a range.
 * 
 *           Strings of the form "xxx yyy" are converted into a pair of
 *           doubles.
 * @param    range_string  The string to be examined.
 * @param    range         A pointer for the returned range.
 * @returns  A pointer to the returned range.
 * @todo     It looks like this routine could do with some error checking.
 */
gdouble*
00427 string_to_range(gchar* range_string)
{
  gdouble* range;
  gchar* second_val_string=NULL;

  range = g_malloc(2*sizeof(gdouble));

  range[0] = g_strtod(range_string, &second_val_string);

  if (second_val_string)
    range[1] = g_strtod(second_val_string+1, NULL);
  else
    range[1] = range[0];

  if (range[0] >= range[1])
    {
      g_free(range);
      return NULL;
    }

  return range;
}

/**
 * @brief    Finds an equal sign "=" in a string.
 * @param    s    The string to be searched.
 * @param    len  The string length of s.
 * @returns  -1 if an equal sign is not found, otherwise the location in
 *           the string.
 */
gint
00458 find_equal(gchar* s, gint len)
{
  gint i;
  for (i=0; i<len; ++i)
    {
      if (s[i] == EQUAL_SIGN)
      return i+1;
    }
  return -1;
}

/**
 * @brief    Return a font spec string corresponding to a chosen font and size.
 * @param    font       The requested base font.
 * @param    font_size  The point size of the font to be returned.
 * @returns  a pointer to the font specification string.
 */
gchar*
00476 get_font(const char* font, gint font_size)
{
  if (actual_font != NULL)
      g_free(actual_font);
  actual_font = g_strdup_printf(font, (int)(font_size * font_size_factor));
  return actual_font;
}


Generated by  Doxygen 1.6.0   Back to index