/* SciGraphica - Scientific graphics and data manipulation * Copyright (C) 2001 Adrian E. Feiguin * * 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 of the License, or * (at your option) any later version. * * 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. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include "sg_layer.h" #include "sg.h" #include "sg_dataset.h" static void sg_layer_init (SGlayer *layer); static void sg_layer_class_init (SGlayerClass *klass); static void sg_layer_destroy (GtkObject *object); static gboolean custom_tick_labels (GtkPlotAxis *axis, gdouble *tick_value, gchar *label, gpointer data); static void plot_changed (GtkPlot *plot, gpointer data); static void clone_axis (GtkPlotAxis *old_axis, GtkPlotAxis *new_axis); static GtkObjectClass *parent_class = NULL; GtkType sg_layer_get_type (void) { static GtkType layer_type = 0; if (!layer_type) { GtkTypeInfo layer_info = { "SGlayer", sizeof (SGlayer), sizeof (SGlayerClass), (GtkClassInitFunc) sg_layer_class_init, (GtkObjectInitFunc) sg_layer_init, /* reserved 1*/ NULL, /* reserved 2 */ NULL, (GtkClassInitFunc) NULL, }; layer_type = gtk_type_unique (GTK_TYPE_OBJECT, &layer_info); } return layer_type; } static void sg_layer_class_init (SGlayerClass *klass) { GtkObjectClass *object_class; parent_class = (GtkObjectClass *)gtk_type_class (gtk_object_get_type ()); object_class = (GtkObjectClass *) klass; object_class->destroy = sg_layer_destroy; } SGlayer * sg_layer_new (SGlayerType layer_type, gdouble width, gdouble height) { SGlayer *layer; GtkPlot *plot; layer = SG_LAYER(gtk_type_new(sg_layer_get_type())); layer->type = layer_type; switch (layer_type){ case SG_LAYER_2D: layer->real_plot = gtk_plot_new_with_size(NULL, width, height); break; case SG_LAYER_3D: layer->real_plot = gtk_plot3d_new_with_size(NULL, width, height); break; case SG_LAYER_POLAR: layer->real_plot = gtk_plot_polar_new_with_size(NULL, width, height); break; } layer->button = gtk_toggle_button_new_with_label(" "); gtk_widget_set_usize(layer->button, 24, 24); plot = GTK_PLOT(layer->real_plot); gtk_plot_set_transparent(plot, TRUE); plot->clip_data = TRUE; gtk_signal_connect(GTK_OBJECT(plot), "changed", GTK_SIGNAL_FUNC(plot_changed), NULL); gtk_signal_connect(GTK_OBJECT(plot->left), "tick_label", GTK_SIGNAL_FUNC(custom_tick_labels), layer); gtk_signal_connect(GTK_OBJECT(plot->right), "tick_label", GTK_SIGNAL_FUNC(custom_tick_labels), layer); gtk_signal_connect(GTK_OBJECT(plot->top), "tick_label", GTK_SIGNAL_FUNC(custom_tick_labels), layer); gtk_signal_connect(GTK_OBJECT(plot->bottom), "tick_label", GTK_SIGNAL_FUNC(custom_tick_labels), layer); return layer; } SGlayer * sg_layer_clone (SGlayer *old_layer) { SGlayer *new_layer; GtkPlot *new_plot, *old_plot; new_layer = sg_layer_new(old_layer->type, GTK_PLOT(old_layer->real_plot)->width, GTK_PLOT(old_layer->real_plot)->height); new_plot = GTK_PLOT(new_layer->real_plot); old_plot = GTK_PLOT(old_layer->real_plot); new_layer->left_labels_worksheet = old_layer->left_labels_worksheet; new_layer->left_labels_column = old_layer->left_labels_column; new_layer->left_values_column = old_layer->left_values_column; new_layer->right_labels_worksheet = old_layer->right_labels_worksheet; new_layer->right_labels_column = old_layer->right_labels_column; new_layer->right_values_column = old_layer->right_values_column; new_layer->top_labels_worksheet = old_layer->top_labels_worksheet; new_layer->top_labels_column = old_layer->top_labels_column; new_layer->top_values_column = old_layer->top_values_column; new_layer->bottom_labels_worksheet = old_layer->bottom_labels_worksheet; new_layer->bottom_labels_column = old_layer->bottom_labels_column; new_layer->bottom_values_column = old_layer->bottom_values_column; new_layer->rescale = old_layer->rescale; clone_axis(old_plot->left, new_plot->left); clone_axis(old_plot->right, new_plot->right); clone_axis(old_plot->bottom, new_plot->bottom); clone_axis(old_plot->top, new_plot->top); new_plot->xmin = old_plot->xmin; new_plot->xmax = old_plot->xmax; new_plot->ymin = old_plot->ymin; new_plot->ymax = old_plot->ymax; new_plot->transparent = old_plot->transparent; new_plot->background = old_plot->background; new_plot->grids_on_top = old_plot->grids_on_top; new_plot->show_x0 = old_plot->show_x0; new_plot->x = old_plot->x; new_plot->y = old_plot->y; new_plot->width = old_plot->width; new_plot->height = old_plot->height; new_plot->xscale = old_plot->xscale; new_plot->yscale = old_plot->yscale; new_plot->bottom_align = old_plot->bottom_align; new_plot->top_align = old_plot->top_align; new_plot->right_align = old_plot->right_align; new_plot->left_align = old_plot->left_align; new_plot->x0_line = old_plot->x0_line; new_plot->y0_line = old_plot->y0_line; new_plot->legends_x = old_plot->legends_x; new_plot->legends_y = old_plot->legends_y; new_plot->legends_border = old_plot->legends_border; new_plot->legends_border_width = old_plot->legends_border_width; new_plot->legends_shadow_width = old_plot->legends_shadow_width; new_plot->show_legends = old_plot->show_legends; new_plot->legends_attr = old_plot->legends_attr; if(GTK_IS_PLOT3D(old_layer->real_plot)){ GtkPlot3D *old_plot3d, *new_plot3d; new_plot3d = GTK_PLOT3D(new_layer->real_plot); old_plot3d = GTK_PLOT3D(old_layer->real_plot); new_plot3d->zmin = old_plot3d->zmin; new_plot3d->zmax = old_plot3d->zmax; new_plot3d->zscale = old_plot3d->zscale; new_plot3d->e1 = old_plot3d->e1; new_plot3d->e2 = old_plot3d->e2; new_plot3d->e3 = old_plot3d->e3; new_plot3d->origin = old_plot3d->origin; new_plot3d->center = old_plot3d->center; new_plot3d->a1 = old_plot3d->a1; new_plot3d->a2 = old_plot3d->a2; new_plot3d->a3 = old_plot3d->a3; new_plot3d->xy_visible = old_plot3d->xy_visible; new_plot3d->yz_visible = old_plot3d->yz_visible; new_plot3d->zx_visible = old_plot3d->zx_visible; new_plot3d->color_xy = old_plot3d->color_xy; new_plot3d->color_yz = old_plot3d->color_yz; new_plot3d->color_zx = old_plot3d->color_zx; new_plot3d->frame = old_plot3d->frame; new_plot3d->corner = old_plot3d->corner; new_plot3d->corner_visible = old_plot3d->corner_visible; new_plot3d->titles_offset = old_plot3d->titles_offset; new_plot3d->xfactor = old_plot3d->xfactor; new_plot3d->yfactor = old_plot3d->yfactor; new_plot3d->zfactor = old_plot3d->zfactor; new_plot3d->zfactor = old_plot3d->zfactor; clone_axis(&old_plot3d->xy, &new_plot3d->xy); clone_axis(&old_plot3d->xz, &new_plot3d->xz); clone_axis(&old_plot3d->yx, &new_plot3d->yx); clone_axis(&old_plot3d->yz, &new_plot3d->yz); clone_axis(&old_plot3d->zx, &new_plot3d->zx); clone_axis(&old_plot3d->zy, &new_plot3d->zy); } if(GTK_IS_PLOT_POLAR(old_layer->real_plot)){ GtkPlotPolar *old_plot, *new_plot; new_plot = GTK_PLOT_POLAR(new_layer->real_plot); old_plot = GTK_PLOT_POLAR(old_layer->real_plot); new_plot->rotation = old_plot->rotation; } return new_layer; } static void clone_axis(GtkPlotAxis *old_axis, GtkPlotAxis *new_axis) { GtkPlotTicks new_ticks; GtkPlotText new_title; new_ticks = new_axis->ticks; new_title = new_axis->title; *new_axis = *old_axis; new_axis->ticks = new_ticks; new_axis->title = new_title; if(old_axis->title.text && strlen(old_axis->title.text) > 0) new_axis->title.text = g_strdup(old_axis->title.text); new_axis->title.x = old_axis->title.x; new_axis->title.y = old_axis->title.y; if(old_axis->labels_prefix && strlen(old_axis->labels_prefix) > 0) new_axis->labels_prefix = g_strdup(old_axis->labels_prefix); if(old_axis->labels_suffix && strlen(old_axis->labels_suffix) > 0) new_axis->labels_suffix = g_strdup(old_axis->labels_suffix); } static void sg_layer_init(SGlayer *layer) { layer->parent = NULL; layer->datasets = NULL; layer->active_data = NULL; layer->left_labels_worksheet = NULL; layer->left_values_column = layer->left_labels_column = -1; layer->right_labels_worksheet = NULL; layer->right_values_column = layer->right_labels_column = -1; layer->top_labels_worksheet = NULL; layer->top_values_column = layer->top_labels_column = -1; layer->bottom_labels_worksheet = NULL; layer->bottom_values_column = layer->bottom_labels_column = -1; layer->symbol = 1; layer->symbol_style = 0; layer->line_style = 1; layer->connector = 1; layer->rescale = 1; gdk_color_black(gdk_colormap_get_system(), &layer->symbol_color); gdk_color_black(gdk_colormap_get_system(), &layer->line_color); } static void sg_layer_destroy(GtkObject *object) { SGlayer *layer; layer = SG_LAYER(object); sg_layer_clear(layer); if(layer->real_plot && GTK_IS_WIDGET(layer->real_plot)) gtk_widget_destroy(layer->real_plot); GTK_OBJECT_CLASS(parent_class)->destroy(object); } static gboolean custom_tick_labels(GtkPlotAxis *axis, gdouble *tick_value, gchar *label, gpointer data) { SGworksheet *worksheet; SGlayer *layer; GtkPlot *plot; gint labels_column, values_column; gchar labels[100]; gint i; layer = (SGlayer *)data; plot = GTK_PLOT(layer->real_plot); if(axis == plot->left){ worksheet = layer->left_labels_worksheet; values_column = layer->left_values_column; labels_column = layer->left_labels_column; } if(axis == plot->right){ worksheet = layer->right_labels_worksheet; values_column = layer->right_values_column; labels_column = layer->right_labels_column; } if(axis == plot->top){ worksheet = layer->top_labels_worksheet; values_column = layer->top_values_column; labels_column = layer->top_labels_column; } if(axis == plot->bottom){ worksheet = layer->bottom_labels_worksheet; values_column = layer->bottom_values_column; labels_column = layer->bottom_labels_column; } g_snprintf(label, 100, "%s", " "); if(!worksheet) return FALSE; if(labels_column < 0) return FALSE; for(i = 0; i <= GTK_SHEET(worksheet->sheet)->maxallocrow; i++){ gchar *vtext, *ltext; gdouble value; vtext = sg_worksheet_cell_get_text(worksheet, i, values_column); if (values_column>=0) { if(vtext) value = atof(vtext); else value = 0.0; } else value=(gdouble)i; if(fabs(value - *tick_value) < 1.e-10){ ltext = sg_worksheet_cell_get_text(worksheet, i, labels_column); if(ltext){ g_snprintf(label, 100, "%s", ltext); }else{ g_snprintf(label, 100, "%s", " "); } return TRUE; } } return FALSE; } void sg_layer_set_tick_labels(SGlayer *layer, gint axis_pos, SGworksheet *worksheet, gint values_col, gint labels_col) { switch(axis_pos){ case GTK_PLOT_AXIS_LEFT: layer->left_labels_worksheet = worksheet; layer->left_labels_column = labels_col; layer->left_values_column = values_col; GTK_PLOT(layer->real_plot)->left->custom_labels = TRUE; break; case GTK_PLOT_AXIS_RIGHT: layer->right_labels_worksheet = worksheet; layer->right_labels_column = labels_col; layer->right_values_column = values_col; GTK_PLOT(layer->real_plot)->right->custom_labels = TRUE; break; case GTK_PLOT_AXIS_TOP: layer->top_labels_worksheet = worksheet; layer->top_labels_column = labels_col; layer->top_values_column = values_col; GTK_PLOT(layer->real_plot)->top->custom_labels = TRUE; break; case GTK_PLOT_AXIS_BOTTOM: layer->bottom_labels_worksheet = worksheet; layer->bottom_labels_column = labels_col; layer->bottom_values_column = values_col; GTK_PLOT(layer->real_plot)->bottom->custom_labels = TRUE; break; } } void sg_layer_add_dataset(SGlayer *layer, SGdataset *dataset) { gtk_plot_add_data(GTK_PLOT(layer->real_plot), dataset->real_data); gtk_widget_show(GTK_WIDGET(dataset->real_data)); layer->datasets = g_list_append(layer->datasets, dataset); } void sg_layer_add_dataset_default(SGlayer *layer, SGdataset *dataset) { dataset->real_data->symbol.symbol_type = (GtkPlotSymbolType)layer->symbol; dataset->real_data->symbol.symbol_style = (GtkPlotSymbolStyle)layer->symbol_style; dataset->real_data->symbol.color = layer->symbol_color; dataset->real_data->symbol.border.color = layer->symbol_color; dataset->real_data->line.line_style = (GtkPlotLineStyle)layer->line_style; dataset->real_data->line_connector = (GtkPlotConnector)layer->connector; dataset->real_data->line.color = layer->line_color; gtk_plot_add_data(GTK_PLOT(layer->real_plot), dataset->real_data); gtk_widget_show(GTK_WIDGET(dataset->real_data)); layer->datasets = g_list_append(layer->datasets, dataset); } void sg_layer_remove_dataset(SGlayer *layer, SGdataset *dataset) { GList *list; SGdataset *link; list = layer->datasets; while(list) { if(list->data == dataset){ link = (SGdataset *)gtk_plot_data_get_link(GTK_PLOT_DATA(dataset->real_data)); link->ref_count--; if(layer->real_plot && GTK_IS_WIDGET(layer->real_plot)){ gtk_plot_remove_data(GTK_PLOT(layer->real_plot), dataset->real_data); } if(GTK_IS_OBJECT(dataset->real_data)){ gtk_widget_destroy(GTK_WIDGET(dataset->real_data)); } gtk_object_destroy(GTK_OBJECT(dataset)); layer->datasets = g_list_remove_link(layer->datasets, list); g_list_free_1(list); break; } list = list->next; } } void sg_layer_clear(SGlayer *layer) { GList *list; list = layer->datasets; while(list){ sg_layer_remove_dataset(layer, SG_DATASET(list->data)); list = layer->datasets; } layer->datasets = NULL; } void sg_layer_button_set_label(SGlayer *layer, gint num) { gchar title[10]; sprintf(title,"%i\n",num); gtk_misc_set_alignment(GTK_MISC(GTK_BIN(layer->button)->child), .5, .0); gtk_label_set_text(GTK_LABEL(GTK_BIN(layer->button)->child), title); } static void plot_changed (GtkPlot *plot, gpointer data) { sg_project_changed(TRUE); } void sg_layer_remove_markers(SGlayer *layer) { SGplot *plot; GtkPlotCanvas *canvas; if(!layer || !layer->active_data) return; plot = (SGplot *)layer->parent; canvas = GTK_PLOT_CANVAS(plot->real_canvas); gtk_plot_data_remove_markers(layer->active_data); layer->active_data = NULL; gtk_plot_canvas_paint(canvas); gtk_plot_canvas_refresh(canvas); } void sg_layer_show_markers(SGlayer *layer, gboolean show) { SGplot *plot; GtkPlotCanvas *canvas; if(!layer || !layer->active_data) return; if(gtk_plot_data_markers_visible(layer->active_data) == show) return; plot = (SGplot *)layer->parent; canvas = GTK_PLOT_CANVAS(plot->real_canvas); gtk_plot_data_show_markers(layer->active_data, show); gtk_plot_canvas_paint(canvas); gtk_plot_canvas_refresh(canvas); } void sg_layer_refresh_datasets(SGlayer *layer) { GList *aux_datasets; aux_datasets = layer->datasets; while(aux_datasets){ SGdataset *data; data = (SGdataset *)aux_datasets->data; sg_dataset_refresh(data); aux_datasets = aux_datasets->next; } } gint sg_layer_min_max(SGlayer *layer, gdouble *xmin, gdouble *xmax, gdouble *ymin, gdouble *ymax) { GtkPlotData *dataset; GList *list; gint n; GtkPlot *plot; gboolean change; plot = GTK_PLOT(layer->real_plot); if(!layer) return FALSE; *xmin = plot->xmin; *ymin = plot->ymin; *xmax = plot->xmax; *ymax = plot->ymax; list = plot->data_sets; while(list){ gdouble fx, fy, fz, fa; gdouble fdx, fdy, fdz, fda; gchar *label; gboolean error; dataset = GTK_PLOT_DATA(list->data); if(!dataset->is_function){ for(n = 0; n < dataset->num_points; n++){ gtk_plot_data_get_point(dataset, n, &fx, &fy, &fz, &fa, &fdx, &fdy, &fdz, &fda, &label, &error); if (n==0 && list==plot->data_sets){ *xmin = fx; *ymin = fy; *xmax = fx; *ymax = fy; change = TRUE; } else { if(fx < *xmin){ change = TRUE; *xmin = fx; } if(fy < *ymin){ change = TRUE; *ymin = fy; } if(fx > *xmax){ change = TRUE; *xmax = fx; } if(fy > *ymax){ change = TRUE; *ymax = fy; } } } } list = list->next; } return change; } void sg_layer_autoscale(SGlayer *layer, gint left_offset, gint right_offset, gint top_offset, gint bottom_offset) { GtkPlotData *dataset; GList *list; gdouble xmin, xmax; gdouble ymin, ymax; gdouble pmin, pmax; gdouble min, max; gdouble pstep; gdouble dx, dy; gint n; gboolean change = FALSE,contour=FALSE; GtkPlot *plot; plot = GTK_PLOT(layer->real_plot); if(!layer) return; if(!layer->datasets) return; list = layer->datasets; while(list){ GtkPlotData *real_data; real_data = GTK_PLOT_DATA(SG_DATASET(list->data)->real_data); if (GTK_IS_PLOT_SURFACE(real_data)){ contour=TRUE; gtk_plot_data_gradient_autoscale_z(real_data); }else if(real_data->iterator_mask & GTK_PLOT_DATA_DA){ gtk_plot_data_gradient_autoscale_da(real_data); }else{ gtk_plot_data_gradient_autoscale_a(real_data); } list=list->next; } if(GTK_IS_PLOT3D(layer->real_plot)){ gtk_plot3d_autoscale(GTK_PLOT3D(layer->real_plot)); return; } change=sg_layer_min_max(layer,&xmin,&xmax,&ymin,&ymax); if(!change) return; if(plot->bottom->scale == GTK_PLOT_SCALE_LOG10) { plot->bottom->ticks.step = 1; plot->bottom->ticks.nminor = 8; xmin = floor(log10(fabs(xmin))) - 1.; xmin = pow(10., xmin); xmax = ceil(log10(fabs(xmax))); xmax = pow(10., xmax); } else { if (!contour && layer->rescale==1){ min = xmin; max = xmax; if(xmin == xmax){ if(xmin == 0.0){ max = xmax = 0.1; }else{ pstep = floor(log10(fabs(xmin))); dx = xmin/pow(10., pstep) * pow(10., pstep); max = xmax = xmin + dx; min = xmin = xmin - dx; } } xmin -= (max - min)*left_offset/100.; xmax += (max - min)*right_offset/100.; if (xmin==xmax) xmax=xmax+1.; dx = (xmax - xmin) / 8.; min = xmin; max = xmax; if (xmin==0.0) xmin -= dx; if (xmax==0.0) xmax += dx; pmin = floor(log10(fabs(xmin))) - 1.; pmax = floor(log10(fabs(xmax))) - 1.; xmin = floor(xmin/pow(10., pmin)) * pow(10., pmin); xmax = floor(xmax/pow(10., pmax)) * pow(10., pmax); pstep = floor(log10(fabs(dx))); dx = plot->bottom->ticks.step = dx/pow(10., pstep) * pow(10., pstep); if (dx!=0){ while(xmin > min) xmin -= dx; while(xmax < max) xmax += dx; } dx = (xmax - xmin)/plot->bottom->ticks.step; while(dx > 5.){ plot->bottom->ticks.step *= 2; dx = floor((xmax - xmin)/plot->bottom->ticks.step); } while (dx < 5){ plot->bottom->ticks.step /= 2; dx = (xmax - xmin)/plot->bottom->ticks.step; } xmin = floor(xmin/plot->bottom->ticks.step) * plot->bottom->ticks.step; xmax = ceil(xmax/plot->bottom->ticks.step) * plot->bottom->ticks.step; plot->top->ticks.step = plot->bottom->ticks.step; } else { if (!contour){ xmin -= (xmax - xmin)*left_offset/100.; xmax += (xmax - xmin)*right_offset/100.; } if (xmin==xmax) xmax=xmin+1.; dx = (plot->bottom->ticks.step!=0?(xmax - xmin)/plot->bottom->ticks.step:(xmax-xmin)/10); while(dx > 5.){ plot->bottom->ticks.step *= 2; dx = floor((xmax - xmin)/plot->bottom->ticks.step); } while(dx < 5.){ plot->bottom->ticks.step /= 2; dx = floor((xmax - xmin)/plot->bottom->ticks.step); } plot->top->ticks.step = plot->bottom->ticks.step; } pstep = floor(log10(fabs(dx))); if (plot->top->label_style==0) plot->top->label_precision = floor(fabs(pstep)); if (plot->bottom->label_style==0) plot->bottom->label_precision = floor(fabs(pstep)); if (plot->bottom->label_style>0) { pstep = (dy!=0?fabs(log10(fabs(dy))):1); plot->bottom->label_precision = ceil(fabs(pstep)); } else { pstep = (plot->bottom->ticks.step!=0?log10(fabs(plot->bottom->ticks.step)):1); if (pstep>=2) pstep=0; if (pstep>0.) pstep=1.; plot->bottom->label_precision = ceil(fabs(pstep)); } if (plot->top->label_style>0) { pstep = (dy!=0?fabs(log10(fabs(dy))):1); if (pstep>=2) pstep=0; if (pstep>0.) pstep=1.; plot->top->label_precision = ceil(fabs(pstep)); } else { pstep = (plot->top->ticks.step!=0?log10(fabs(plot->top->ticks.step)):1); if (pstep>=2) pstep=0; if (pstep>0) pstep=1; plot->top->label_precision = ceil(fabs(pstep)); } } if(plot->left->scale == GTK_PLOT_SCALE_LOG10) { plot->left->ticks.step = 1; plot->left->ticks.nminor = 8; ymin = floor(log10(fabs(ymin))) - 1.; ymin = pow(10., ymin); ymax = ceil(log10(fabs(ymax))); ymax = pow(10., ymax); } else { if (!contour && layer->rescale==1){ min = ymin; max = ymax; if(ymin == ymax){ if(ymin == 0.0){ max = ymax = 0.1; }else{ pstep = floor(log10(fabs(ymin))); dy = ymin/pow(10., pstep) * pow(10., pstep); max = ymax = ymin + dy; min = ymin = ymin - dy; } } ymin -= (max - min)*bottom_offset/100.; ymax += (max - min)*top_offset/100.; if (ymin==ymax) ymax=ymax+1.; dy = (ymax - ymin) / 8.; min = ymin; max = ymax; if (ymin==0.0) ymin -= dy; if (ymax==0.0) ymax += dy; pmin = floor(log10(fabs(ymin))) - 1.; pmax = floor(log10(fabs(ymax))) - 1.; ymin = floor(ymin/pow(10., pmin)) * pow(10., pmin); ymax = floor(ymax/pow(10., pmax)) * pow(10., pmax); pstep = floor(log10(fabs(dy))); dy = plot->left->ticks.step = dy/pow(10., pstep) * pow(10., pstep); if (dy!=0){ while(ymin > min) ymin -= dy; while(ymax < max) ymax += dy; } dy = (ymax - ymin)/plot->left->ticks.step; while(dy > 5.){ plot->left->ticks.step *= 2; dy = floor((ymax - ymin)/plot->left->ticks.step); } while (dy < 5){ plot->left->ticks.step /= 2; dy = (ymax - ymin)/plot->left->ticks.step; } ymin = floor(ymin/plot->left->ticks.step) * plot->left->ticks.step; ymax = ceil(ymax/plot->left->ticks.step) * plot->left->ticks.step; plot->right->ticks.step = plot->left->ticks.step; } else { if (!contour){ ymin -= (ymax - ymin)*bottom_offset/100.; ymax += (ymax - ymin)*top_offset/100.; } if (ymin==ymax) ymax=ymin+1.; dy = (plot->left->ticks.step!=0?(ymax - ymin)/plot->left->ticks.step:(ymax-ymin)/10); while (dy > 5.){ plot->left->ticks.step *= 2; dy = floor((ymax - ymin)/plot->left->ticks.step); } plot->right->ticks.step = plot->left->ticks.step; while (dy < 5){ plot->left->ticks.step /= 2; dy = (ymax - ymin)/plot->left->ticks.step; } plot->right->ticks.step = plot->left->ticks.step; } if (plot->left->label_style>0) { pstep = (dy!=0?fabs(log10(fabs(dy))):1); plot->left->label_precision = ceil(fabs(pstep)); } else { pstep = (plot->left->ticks.step!=0?log10(fabs(plot->left->ticks.step)):1); if (pstep>=2) pstep=0; if (pstep>0.) pstep=1.; plot->left->label_precision = ceil(fabs(pstep)); } if (plot->right->label_style>0) { pstep = (dy!=0?fabs(log10(fabs(dy))):1); if (pstep>=2) pstep=0; if (pstep>0.) pstep=1.; plot->right->label_precision = ceil(fabs(pstep)); } else { pstep = (plot->right->ticks.step!=0?log10(fabs(plot->right->ticks.step)):1); if (pstep>=2) pstep=0; if (pstep>0) pstep=1; plot->right->label_precision = ceil(fabs(pstep)); } } gtk_plot_set_range(plot, xmin, xmax, ymin, ymax); }