From: trelane@digitasaru.net Date: Mon, 12 Oct 2009 12:26:14 +0000 (-0500) Subject: Moving files around, starting libtoolization. X-Git-Url: http://git.maemo.org/git/?p=scdataviz;a=commitdiff_plain;h=ca8d26a012451771595cf54194888b1984c5dd17 Moving files around, starting libtoolization. --- diff --git a/Makefile b/Makefile deleted file mode 100644 index 3922e81..0000000 --- a/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -## -## Makefile -## -## Made by Johnny Q. Hacker -## Login -## -## Started on Thu Jul 17 10:56:05 2008 Johnny Q. Hacker -## Last update Thu Jul 17 10:56:05 2008 Johnny Q. Hacker -## -############################## -# Complete this to make it ! # -############################## -NAME = scdataviz # Name of executable file -SRC = $(wildcard *.c) # List of *.c -INCL = # List of *.h -################ -# Optional add # -################ -IPATH = -I. # path of include file -OBJOPT = -ggdb -g3 -pg -Wall -Wstrict-prototypes -DDEBUG -std=c99 -D_GNU_SOURCE # option for obj -EXEOPT = -ggdb -g3 -pg -Wall -Wstrict-prototypes -std=c99 -D_GNU_SOURCE # option for exe (-lefence ...) -LPATH = -L. # path for librairies ... - -##################### -# Macro Definitions # -##################### -CC = gcc -MAKE = make -SHELL = /bin/sh -OBJS = $(SRC:.c=.o) -RM = /bin/rm -f -COMP = gzip -9v -UNCOMP = gzip -df -STRIP = strip - -CFLAGS = $(OBJOPT) $(IPATH) `pkg-config --cflags gtk+-2.0` -LDFLAGS = $(EXEOPT) $(LPATH) `pkg-config --libs gtk+-2.0` - -.SUFFIXES: .h.Z .c.Z .h.gz .c.gz .c.z .h.z - -############################## -# Basic Compile Instructions # -############################## - -all: $(NAME) -$(NAME): $(OBJS) $(SRC) $(INCL) - $(CC) $(OBJS) $(LDFLAGS) -o $(NAME) -# $(STRIP) ./$(NAME) # if you debug ,don't strip ... - -depend: - gcc $(IPATH) -MM $(SRC) -clean: - -$(RM) $(NAME) $(OBJS) -fclean: - -$(RM) $(NAME) -comp: clean - $(COMP) $(INCL) $(SRC) -ucomp: - $(UNCOMP) $(SRC) $(INCL) - -.c.Z.c .h.Z.h .c.gz.c .h.gz.h .c.z.c .h.z.h : - -$(UNCOMP) $< - -.c.o: - $(CC) $(CFLAGS) -c $< -################ -# Dependencies # -################ diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..6809a32 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,38 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +AUTOMAKE_OPTIONS = gnu subdir-objects +AM_DEFAULT_SOURCE_EXT = .c++ +ACLOCAL_AMFLAGS=-I m4 +AM_YFLAGS=-d +AM_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) +AM_CPPFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) + +bin_PROGRAMS = kdotp/kdotp kdotp/makestruct +lib_LTLIBRARIES = libkdotp/libkdotp-0.1.la libmodelxx/libmodelxx-0.1.la + +#Tests which should succeed +TESTS=tests/tests + +check_PROGRAMS = tests/tests +tests_tests_SOURCES = +LIBS += -lm +#Tests which should fail. +XFAIL_TESTS= + +CLEANFILES = program_version.c + +program_version.c: + echo -n 'char *version_info = "' > program_version.c + bzr version-info | perl -ne 'chomp; print; print "\\n";' >> program_version.c + echo '";' >> program_version.c + +include_HEADERS= +include libkdotp.am +include libmodelxx.am + +kdotp_kdotp_SOURCES = kdotp/kdotp.c++ +kdotp_kdotp_LDADD = libkdotp/libkdotp-0.1.la +LIBS += $(GLIB_LIBS) $(GIO_LIBS) + +kdotp_makestruct_SOURCES = kdotp/makestruct.c++ kdotp/structspec_parser.y++ kdotp/structspec_lexer.l++ +kdotp_makestruct_LDADD = libkdotp/libkdotp-0.1.la libmodelxx/libmodelxx-0.1.la +LIBS += $(GLIB_LIBS) $(GIO_LIBS) diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..178e8d4 --- /dev/null +++ b/configure.ac @@ -0,0 +1,128 @@ +AC_PREREQ(2.61) +AC_INIT([gimme-alpha], [0.1], [gimme-alpha@pingenot.org]) +AM_INIT_AUTOMAKE([gnu -Wno-portability]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_LIBTOOL +AC_PROG_INSTALL +AM_PROG_LEX +AC_PROG_YACC + +PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.6, have_glib=true, have_glib=false) +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.18, have_gio=true, have_gio=false) +AC_SUBST(GIO_CFLAGS) +AC_SUBST(GIO_LIBS) + +PKG_CHECK_MODULES(FFTW3, fftw3 >= 3.1.2, have_fftw3=true, have_fftw3=false) +AC_SUBST(FFTW3_CFLAGS) +AC_SUBST(FFTW3_LIBS) + +dnl Check for GNU Scientific Lib, link to it if found. +AC_CHECK_LIB([m],[cos]) +AC_CHECK_LIB([gslcblas],[cblas_dgemm]) +AC_CHECK_LIB([gsl],[gsl_blas_dgemm]) + +dnl PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 3.1, have_gtk=true, have_gtk=false) +dnl AC_SUBST(GTK_CFLAGS) +dnl AC_SUBST(GTK_LIBS) + +AC_ARG_ENABLE([debug], +[ --enable-debug Turn on debugging], +[case "${enableval}" in + yes) debug=true ;; + no) debug=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; +esac],[debug=false]) +AM_CONDITIONAL([DEBUG], [test x$debug = xtrue]) + +COMMMON_CFLAGS="-pipe -Wall -Werror -std=gnu99 -pedantic -Wno-unused-variable -Wno-unused-label -Wno-unused-parameter -Wno-unused-value -Wno-unused-function -march=native -mfpmath=sse -msse -mmmx -msse2 -msse3 -mssse3 -ftracer -fbranch-target-load-optimize" +if test "x$debug" = "xtrue"; then + CFLAGS="$COMMMON_CFLAGS -O0 -g3" +else + CFLAGS="$COMMMON_CFLAGS -O3 -frename-registers " +fi +dnl CPPFLAGS= + +AC_ARG_ENABLE([mudflap], +[ --enable-mudflap Turn on mudflap, which debugs pointer use (verbosely)], +[case "${enableval}" in + yes) mudflap=true ;; + no) mudflap=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-mudflap]) ;; +esac],[mudflap=false]) +AM_CONDITIONAL([MUDFLAP], [test x$mudflap = xtrue]) +if test "x$mudflap" = "xtrue"; then + CFLAGS="$CFLAGS -fmudflap -lmudflap" +fi + +AC_ARG_ENABLE([profiling], +[ --enable-profiling Turn on profiling], +[case "${enableval}" in + yes) profiling=true ;; + no) profiling=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-profiling]) ;; +esac],[profiling=false]) +AM_CONDITIONAL([PROFILING], [test x$profiling = xtrue]) +if test "x$profiling" = "xtrue"; then + CFLAGS="$CFLAGS -pg -fprofile-generate" +fi + +AC_ARG_ENABLE([openmpi], +[ --enable-openmpi Turn on OpenMPI support], +[case "${enableval}" in + yes) openmpi=true ;; + no) openmpi=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-openmpi]) ;; +esac],[mkl=false]) +AM_CONDITIONAL([OPENMPI], [test x$openmpi = xtrue]) +if test "x$openmpi" = "xtrue"; then + CFLAGS="$CFLAGS -DOPENMPI" +fi + +AC_ARG_ENABLE([acml], +[ --enable-acml Turn on AMD Core Math Library support], +[case "${enableval}" in + yes) acml=true ;; + no) acml=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-acml]) ;; +esac],[mkl=false]) +AM_CONDITIONAL([ACML], [test x$acml = xtrue]) +if test "x$acml" = "xtrue"; then + CFLAGS="$CFLAGS -DACML" +fi + +AC_ARG_ENABLE([mkl], +[ --enable-mkl Turn on Intel's Math Kernel Library support], +[case "${enableval}" in + yes) mkl=true ;; + no) mkl=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-mkl]) ;; +esac],[mkl=false]) +AM_CONDITIONAL([MKL], [test x$mkl = xtrue]) +if test "x$mkl" = "xtrue"; then + CFLAGS="$CFLAGS -DMKL" +fi + +AC_ARG_ENABLE([atlas], +[ --enable-atlas Turn on ATLAS support], +[case "${enableval}" in + yes) atlas=true ;; + no) atlas=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-atlas]) ;; +esac],[atlas=false]) +AM_CONDITIONAL([ATLAS], [test x$atlas = xtrue]) +if test "x$atlas" = "xtrue"; then + CFLAGS="$CFLAGS -DATLAS" +fi + +LIBKDOTP_ABI_VERSION=0 +LIBMODELXX_ABI_VERSION=0 + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/graph.c b/graph.c deleted file mode 100644 index cd2b056..0000000 --- a/graph.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -** Graph.c -** -** Made by (Johnny Q. Hacker) -** Login -** - - -Copyright (C) 2008 Joseph Pingenot - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . - - -**Many thanks to Davyd Madeley for the excellent Cairo Tutorial -** at http://gnomejournal.org/article/34/writing-a--using-cairo-and-gtk28 - -** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker -** Last update Sun May 12 01:17:25 2002 Speed Blue -*/ - -#include -#include -#include -#include - -#ifdef DEBUG -#define DEBUG_AUTOAXIS -#endif - -G_DEFINE_TYPE(Graph, graph, G_TYPE_OBJECT); - -static void graph_class_init(GraphClass *klass) { - GObjectClass *gobject_klass; - gobject_klass = G_OBJECT_CLASS(klass); -} - -static void graph_init(Graph *graph) { - graph->symbol = CIRCLE; - graph->points = g_ptr_array_new(); - graph->lines = NULL; - graph->xaxis = graph->yaxis = NULL; -} - -Graph *graph_new(void) { - return g_object_new(GRAPH_TYPE, NULL); -} - -/*1 means you're stupid and passed NULL*/ -int graph_add_graph_point(Graph* graph, struct graph_point *pt) { - if(pt == NULL) return 1; - g_ptr_array_add(graph->points, pt); - if((graph->points->len == 1) && ((graph->lines == NULL) || (graph->lines->len == 0))) { - graph->maxx = graph->minx = pt->x; - graph->maxy = graph->miny = pt->y; - }else{ - if(pt->x > graph->maxx) graph->maxx = pt->x; - if(pt->x < graph->minx) graph->minx = pt->x; - if(pt->y > graph->maxy) graph->maxy = pt->y; - if(pt->y < graph->miny) graph->miny = pt->y; - } - return 0; -} - -/* - * - *1 means failed to allocate point - *NOTE: label is duplicated if not NULL (using g_strdup) - */ -int graph_add_point(Graph* graph, double x, double y, const GString *label) { - struct graph_point *pt = (struct graph_point*)malloc(sizeof(struct graph_point)); - if(pt == NULL) return 1; - pt->x = x; - pt->y = y; - pt->label = (label)?g_string_new(label->str):NULL; - graph_add_graph_point(graph, pt); - return 0; -} - -int graph_add_graph_line(Graph* graph, struct graph_line *l) { - if(l == NULL) return 1; - if(graph->lines == NULL) { - if((graph->lines = g_ptr_array_new()) == NULL) return 1; - } - g_ptr_array_add(graph->lines, l); - if((graph->points->len == 0) && - (graph->lines->len == 1)) { - graph->maxx = graph->minx = l->p0_x; - graph->maxy = graph->miny = l->p0_y; - }else{ - if(l->p0_x > graph->maxx) graph->maxx = l->p0_x; - if(l->p0_x < graph->minx) graph->minx = l->p0_x; - if(l->p0_y > graph->maxy) graph->maxy = l->p0_y; - if(l->p0_y < graph->miny) graph->miny = l->p0_y; - } - if(l->p3_x > graph->maxx) graph->maxx = l->p3_x; - if(l->p3_x < graph->minx) graph->minx = l->p3_x; - if(l->p3_y > graph->maxy) graph->maxy = l->p3_y; - if(l->p3_y < graph->miny) graph->miny = l->p3_y; - return 0; -} - - -int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y) { - #ifdef DEBUG - fprintf(stderr, "graph_add_line(%d, p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", (unsigned int) graph, p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y); - #endif - struct graph_line *l; - if((l=(struct graph_line*)malloc(sizeof(struct graph_line))) == NULL) return 2; - l->p0_x=p0_x; - l->p0_y=p0_y; - l->p1_x=p1_x; - l->p1_y=p1_y; - l->p2_x=p2_x; - l->p2_y=p2_y; - l->p3_x=p3_x; - l->p3_y=p3_y; - return graph_add_graph_line(graph, l); -} - -struct cxt { - Graph *graph; - struct graph_point *p0; -}; - -static void linear_interpolate(gpointer data, gpointer user_data) { - struct cxt *cxt = user_data; - struct graph_point *p3 = data; - if(cxt->p0 != NULL) { - double p1_x = (p3->x + 2*cxt->p0->x)/3.0; - double p1_y = (p3->y + 2*cxt->p0->y)/3.0; - double p2_x = (2*p3->x + cxt->p0->x)/3.0; - double p2_y = (2*p3->y + cxt->p0->y)/3.0; - graph_add_line(cxt->graph, cxt->p0->x, cxt->p0->y, p1_x, p1_y, p2_x, p2_y, p3->x, p3->y); - } - cxt->p0 = p3; -} - -void graph_add_linear_connectors(Graph* graph) { - struct cxt cxt; - cxt.graph = graph; - cxt.p0 = NULL; - g_ptr_array_foreach(graph->points, &linear_interpolate, &cxt); -} - -void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2) { - *x1 = (x3 + 2.0*x0)/3.0; - *x2 = (2.0*x3 + x0)/3.0; -} - -void graph_bezier_linear_to_quadratic(double x0, double x3, double *x1) { - *x1 = (x3 + x0)/2.0; -} - -void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2) { - *x2 = (x3-2.0*(*x1))/3.0; - *x1 = (x0-2.0*(*x1))/3.0; -} - -void graph_set_xaxis(Graph *g, struct graph_axis *axis) { - if(g->xaxis != NULL) { - free(g->xaxis); - } - g->xaxis=axis; -} -void graph_set_yaxis(Graph *g, struct graph_axis *axis) { - if(g->yaxis != NULL) { - free(g->yaxis); - } - g->yaxis=axis; -} - -struct graph_axis* autoset_axis(Graph* g, GString* title, double min, double max) { - struct graph_axis *axis; - double range_mag; - double start_mag; - double stop_mag; - int i, j; - if(g->points->len == 0) { - return NULL; - } - if((axis=(struct graph_axis *)malloc(sizeof(struct graph_axis))) == NULL) { - return NULL; - } - if(g->points->len == 1) { - axis->major=1; - axis->minor=0; - axis->subminor=0; - axis->major_start=min; - axis->major_step=max; - }else{ - range_mag = logb(max - min); - if(min == 0) - start_mag = 0; - else - start_mag = copysign(pow(10, floor(log10(min))), min); - if(max == 0) - stop_mag = 0; - else - stop_mag = copysign(pow(10, ceil(log10(max))), max); - for(i=1; i<9; i++) { - if(i*start_mag > min) break; - } - i--; - for(j=10; j>1; j--) { - if(j*(stop_mag/10) < max) break; - } - j++; - axis->major=10; - axis->minor=1; - axis->subminor=4; - axis->major_start=i*start_mag; - axis->major_step=(j*(stop_mag/10) - axis->major_start)/(axis->major); - } - axis->title=g_string_new(title->str); - #ifdef DEBUG_AUTOAXIS - fprintf(stderr, "graph_autoset_xaxis: xmin=%g, log10(xmin)=%g, floor=%g, pow=%g round=%g\n", min, log10(min), floor(log10(min)), pow(10, floor(log10(min))), round(pow(10, floor(log10(min))))); - fprintf(stderr, "graph_autoset_xaxis: xmax=%g, log10(xmax)=%g, floor=%g, pow=%g round=%g\n", max, log10(max), floor(log10(max)), pow(10, floor(log10(max))), round(pow(10, floor(log10(max))))); - fprintf(stderr, "graph_autoset_xaxis: xmin=%g,max=%g start_mag=%g, stop_mag=%g range_mag=%g\n", min, max, start_mag, stop_mag, range_mag); - #endif - return axis; -} - -int graph_autoset_xaxis(Graph *g, GString *title) { - graph_set_xaxis(g, autoset_axis(g, title, g->minx, g->maxx)); - return 0; -} - -int graph_autoset_yaxis(Graph *g, GString *title) { - graph_set_yaxis(g, autoset_axis(g, title, g->miny, g->maxy)); - return 0; -} diff --git a/graph.h b/graph.h deleted file mode 100644 index 31d441f..0000000 --- a/graph.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -** Graph.h -** -** Made by Johnny Q. Hacker -** Login -** - - Copyright (C) 2008 Joseph Pingenot - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker -** Last update Thu Jul 17 10:51:32 2008 Johnny Q. Hacker -*/ - -#ifndef GRAPHCLASS_H_ -#define GRAPHCLASS_H_ - -#include - -typedef enum {SQUARE, CIRCLE, STAR, PLUS, MINUS, CROSS} graph_symbol; - -struct graph_point { - double x; - double y; - GString *label; -}; - -/*Bezier line*/ -struct graph_line { - /*First point*/ - double p0_x; - double p0_y; - /*Control pts*/ - double p1_x; - double p1_y; - double p2_x; - double p2_y; - /*End point*/ - double p3_x; - double p3_y; -}; - -struct graph_axis { - double major_start; - double major_step; - int major; - int minor; - int subminor; - GString *title; -}; - -typedef struct _Graph { - GObject parent_instance; - /*Array of n_points sets of x,y coords*/ - GPtrArray *points; - /*This draws all of the lines (generally between points)*/ - GPtrArray *lines; - double maxx; - double minx; - double maxy; - double miny; - graph_symbol symbol; - struct graph_axis *xaxis; - struct graph_axis *yaxis; -} Graph; - -typedef struct _GraphClass { - GObjectClass parent_class; -} GraphClass; - -#define GRAPH_TYPE (graph_get_type()) -#define GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_TYPE, Graph)) -#define GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH, GraphClass)) -#define IS_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_TYPE)) -#define IS_GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_CLASS_TYPE)) -#define GRAPH_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH, GraphClass)) - -Graph *graph_new(void); -int graph_add_point(Graph* graph, double x, double y, const GString *label); -int graph_add_graph_point(Graph* graph, struct graph_point *pt); -int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y); -int graph_add_graph_line(Graph* graph, struct graph_line *l); -void graph_add_linear_connectors(Graph* graph); -/*Provide x0, x3; x1 and x2 will be set*/ -void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2); -/*Provide x0, x1, x2. x1 and x2 will be set appropriately.*/ -void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2); -void graph_set_xaxis(Graph *g, struct graph_axis *axis); -void graph_set_yaxis(Graph *g, struct graph_axis *axis); -int graph_autoset_xaxis(Graph *g, GString *title); -int graph_autoset_yaxis(Graph *g, GString *title); - - - -#endif /* !GRAPHCLASS_H_ */ diff --git a/graphwidget.c b/graphwidget.c deleted file mode 100644 index beba3c9..0000000 --- a/graphwidget.c +++ /dev/null @@ -1,252 +0,0 @@ -/* -** Graph.c -** -** Made by (Johnny Q. Hacker) -** Login -** - - - - Copyright (C) 2008 Joseph Pingenot - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -**Many thanks to Davyd Madeley for the excellent Cairo Widget Tutorial -** at http://gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28 - -** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker -** Last update Thu Oct 8 17:13:50 2009 Johnny Q. Hacker -*/ - -#include -#include - -G_DEFINE_TYPE(GraphWidget, graph_widget, GTK_TYPE_DRAWING_AREA); - -#define INSET_PERCENT 0.1 -#define TITLE_PERCENT 0.15 -#define DEBUG_DRAW_AXIS - -struct drawing_context { - GtkWidget *widget; - cairo_t *cr; - double radius; - double xoffset; - double yoffset; - double xscaling; - double yscaling; - /*Semi-normalized maxima*/ - double xmax; - double ymax; - cairo_matrix_t data_scale; - cairo_matrix_t data_xlat; -}; - -static void draw_point(gpointer data, gpointer user_data) { - struct drawing_context *cxt = user_data; - struct graph_point *pt = data; - double x = (pt->x + cxt->xoffset)*cxt->xscaling; - double y = (pt->y + cxt->yoffset)*cxt->yscaling; - cairo_move_to(cxt->cr, x, y); - cairo_arc(cxt->cr, x, y, cxt->radius, 0, 2*M_PI); - if(pt->label != NULL) { - cairo_save(cxt->cr); - cairo_scale(cxt->cr, 1, -1); - cairo_show_text(cxt->cr, pt->label->str); - cairo_restore(cxt->cr); - } -} - -static void draw_lines(gpointer data, gpointer user_data) { - struct drawing_context *cxt = user_data; - struct graph_line *l = data; - double p0_x = (l->p0_x + cxt->xoffset)*cxt->xscaling; - double p0_y = (l->p0_y + cxt->yoffset)*cxt->yscaling; - double p1_x = (l->p1_x + cxt->xoffset)*cxt->xscaling; - double p1_y = (l->p1_y + cxt->yoffset)*cxt->yscaling; - double p2_x = (l->p2_x + cxt->xoffset)*cxt->xscaling; - double p2_y = (l->p2_y + cxt->yoffset)*cxt->yscaling; - double p3_x = (l->p3_x + cxt->xoffset)*cxt->xscaling; - double p3_y = (l->p3_y + cxt->yoffset)*cxt->yscaling; - #ifdef DEBUG_DRAW - fprintf(stderr, "draw_lines: p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y); - #endif - cairo_move_to(cxt->cr, p0_x, p0_y); - cairo_curve_to(cxt->cr, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y); -} - -static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis, double scaling, double offset, double max) { - #ifdef DEBUG_DRAW_AXIS - fprintf(stderr, "draw_axis; major_start=%g, major_step=%g, >major=%d, minor=%d, subminor=%d, label=%s\n", axis->major_start, axis->major_step, axis->major, axis->minor, axis->subminor, axis->title->str); - #endif - cairo_move_to(cxt->cr, 0, 0); - cairo_line_to(cxt->cr, max, 0); - register int i, j, k; - register double pos, mpos, smpos; - for(i=0; imajor; i++) { - pos=i*axis->major_step + axis->major_start; - cairo_move_to(cxt->cr, (pos + offset)*scaling, 0); - cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05); - for(k=0; ksubminor; k++) { - smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + pos; - cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0); - cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125); - } - for(j=0; jminor; j++) { - mpos=(j+1)*(axis->major_step/(axis->minor+1)) + pos; - cairo_move_to(cxt->cr, (mpos + offset)*scaling, 0); - cairo_line_to(cxt->cr, (mpos + offset)*scaling, 0.025); - for(k=0; ksubminor; k++) { - smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + mpos; - cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0); - cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125); - } - } - } - pos=i*axis->major_step + axis->major_start; - cairo_move_to(cxt->cr, (pos + offset)*scaling, 0); - cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05); -} - -static void draw(GtkWidget *graph, cairo_t *cr) { - struct drawing_context cxt; - GraphWidget *gw = GRAPH_WIDGET(graph); - #ifdef DEBUG_DRAW - fprintf(stderr, "draw(%d, %d)\n", (int)graph, (int)cr); - fprintf(stderr, "allocation.x=%d, allocation.y=%d, allocation.height=%d, allocation.width=%d\n", graph->allocation.x, graph->allocation.y, graph->allocation.height, graph->allocation.width); - #endif - double x0=graph->allocation.x; - double y0=graph->allocation.y; - double height=graph->allocation.height; - double width=graph->allocation.width; - double minx = gw->graph->minx; - double maxx = gw->graph->maxx; - double miny = gw->graph->miny; - double maxy = gw->graph->maxy; - if(gw->graph->xaxis != NULL) { - minx = gw->graph->xaxis->major_start; - maxx = gw->graph->xaxis->major_start + gw->graph->xaxis->major_step*gw->graph->xaxis->major; - } - if(gw->graph->yaxis != NULL) { - miny = gw->graph->yaxis->major_start; - maxy = gw->graph->yaxis->major_start + gw->graph->yaxis->major_step*gw->graph->yaxis->major; - } - cxt.widget = graph; - cxt.cr = cr; - cxt.radius = 0.01; - /*Set up our semi-normalized scaling. The shortest direction range - [0, 1]; the other range depends upon the relative sizes.*/ - double effective_height = height; - double effective_width = width; - double inset, axis_inset; - if((INSET_PERCENT > 0) && (INSET_PERCENT < 1.0)) { - inset = ((effective_height > effective_width)?effective_width:effective_height)*INSET_PERCENT; - effective_height -= inset; - effective_width -= inset; - } - if((gw->graph->xaxis != NULL) && (gw->graph->yaxis != NULL)) { - /*key off the smaller size.*/ - axis_inset = ((effective_height > effective_width)?effective_width:effective_height)*TITLE_PERCENT; - effective_height -= axis_inset; - effective_width -= axis_inset; - }else if(gw->graph->xaxis != NULL) { - effective_height -= effective_height*TITLE_PERCENT; - }else if(gw->graph->yaxis != NULL) { - effective_width -= effective_width*TITLE_PERCENT; - } - if(effective_width > effective_height) { - cxt.xmax = effective_width/effective_height; - cxt.ymax = 1.0; - }else{ - cxt.xmax = 1.0; - cxt.ymax = effective_height/effective_width; - } - /*Convert from data space to the semi-normalized space*/ - double xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(maxx-minx)); - double yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(maxy-miny)); - double xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx); - double yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny); - /*Finish up our context information.*/ - cxt.xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(((maxx - minx)==0)?1:(maxx-minx))); - cxt.yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(((maxy - miny)==0)?1:(maxy-miny))); - cxt.xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx); - cxt.yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny); - cairo_matrix_translate(&(cxt.data_xlat), xoffset, yoffset); - cairo_matrix_scale(&(cxt.data_scale), xscaling, yscaling); - #ifdef DEBUG - fprintf(stderr, "minx=%g, maxx=%g, miny=%g, maxy=%g, xscaling=%g, yscaling=%g, xoffset=%g, yoffset=%g\n", minx, maxx, miny, maxy, cxt.xscaling, cxt.yscaling, cxt.xoffset, cxt.yoffset); - fprintf(stderr, "x0=%g, y0=%g, width=%g, height=%g\n", x0, y0, height, width); - fprintf(stderr, "translate=(%g, %g)\n", x0 + ((width>height)?(width-height)/2.0:0), y0+((width > height)?height:width) + ((height>width)?(height-width)/2.0:0)); - #endif - double offset_height = ((width>=height)?height*INSET_PERCENT:0);; - double offset_width = ((height>=width)?width*INSET_PERCENT:0); - double inset_height = height - offset_height; - double inset_width = width - offset_width; - cairo_save(cr); - cairo_translate(cr, x0 + (width - effective_width) - inset/2, y0 + effective_height + inset/2); - cairo_scale(cr, effective_width/cxt.xmax, -effective_height/cxt.ymax); - cairo_set_line_width(cr, 0.005); - cairo_select_font_face (cr, "Georgia", - CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); - cairo_set_font_size (cr, 0.05); - if(gw->graph->lines != NULL) { - cairo_set_source_rgba(cr, 0, 0, 0, 0.25); - g_ptr_array_foreach(gw->graph->lines, &draw_lines, (gpointer)&cxt); - cairo_stroke(cr); - } - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill_preserve(cr); - cairo_set_source_rgb(cr, 0, 0, 0); - g_ptr_array_foreach(gw->graph->points, &draw_point, (gpointer)&cxt); - if(gw->graph->xaxis != NULL) - draw_axis(&cxt, gw->graph->xaxis, cxt.xscaling, cxt.xoffset, cxt.xmax); - if(gw->graph->yaxis != NULL) { - cairo_save(cr); - cairo_matrix_t matrix = { .xx=0, .xy = 1, .x0 = 0, .yx = 1, .yy = 0, .y0 = 0 }; - cairo_transform(cr, &matrix); - draw_axis(&cxt, gw->graph->yaxis, cxt.yscaling, cxt.yoffset, cxt.ymax); - cairo_restore(cr); - } - cairo_stroke(cr); - cairo_restore(cr); -} - -static gboolean graph_widget_expose(GtkWidget *graph, GdkEventExpose *event) { - cairo_t *cr = gdk_cairo_create(graph->window); - cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height); - cairo_clip(cr); - draw(graph, cr); - cairo_destroy(cr); - return FALSE; -} - -static void graph_widget_class_init(GraphWidgetClass *klass) { - GtkWidgetClass *widget_class; - widget_class = GTK_WIDGET_CLASS(klass); - widget_class->expose_event = graph_widget_expose; -} - -static void graph_widget_init(GraphWidget *graph) { - /*Get a graph.*/ - graph->graph = graph_new(); -} - -GtkWidget *graph_widget_new(void) { - return g_object_new(GRAPH_WIDGET_TYPE, NULL); -} - -Graph* graph_widget_get_graph(GraphWidget* gw) { - return gw->graph; -} - diff --git a/graphwidget.h b/graphwidget.h deleted file mode 100644 index cb2e390..0000000 --- a/graphwidget.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -** Graph.h -** -** Made by Johnny Q. Hacker -** Login -** - - - - Copyright (C) 2008 Joseph Pingenot - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker -** Last update Thu Oct 8 14:28:34 2009 Johnny Q. Hacker -*/ - -#ifndef GRAPHWIDGET_H_ -#define GRAPHWIDGET_H_ - -#include -#include - -typedef struct _GraphWidget { - GtkDrawingArea parent_instance; - Graph *graph; -} GraphWidget; - -typedef struct _GraphWidgetClass { - GtkDrawingAreaClass parent_class; -} GraphWidgetClass; - -#define GRAPH_WIDGET_TYPE (graph_widget_get_type()) -#define GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_WIDGET_TYPE, GraphWidget)) -#define GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH_WIDGET, GraphWidgetClass)) -#define IS_GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_WIDGET_TYPE)) -#define IS_GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_WIDGET_CLASS_TYPE)) -#define GRAPH_WIDGET_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH_WIDGET, GraphWidgetClass)) - -GtkWidget* graph_widget_new(void); - -Graph* graph_widget_get_graph(GraphWidget* gw); - -#endif /* !GRAPHWIDGET_H_ */ diff --git a/matdb-dotcode.c b/matdb-dotcode.c deleted file mode 100644 index df195fb..0000000 --- a/matdb-dotcode.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * matdb-dotcode: reads in Craig's Dotcode materials database. - - - - Copyright (C) 2008 Joseph Pingenot - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -*/ - -#include -#define _GNU_SOURCE -#include -#include -#include - -#ifdef DEBUG -#undef DEBUG -#endif -#ifdef DEBUG_2 -#undef DEBUG_2 -#endif - -/*Functions to be used by the hash.*/ -static void destroy_string(gpointer data) { - free((char*)data); -} -static void destroy_double(gpointer data){ - free((double*)data); -} -static void destroy_inner_bowhash(gpointer data) { - g_hash_table_unref(data); -} - -int insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) { - if((*mat) != NULL) { -#ifdef DEBUG - fprintf(stderr, "inserting material %s\n", (*mat)->name->str); -#endif - g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat)); - (*mat) = NULL; - } - if((*bow) != NULL) { -#ifdef DEBUG - fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str); -#endif - /*Inner table*/ - GHashTable *it; - if((it=g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) { - if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) { - (*bow) = NULL; - return 1; - } - g_hash_table_insert(mdb->bowings, (*bow)->from->str, it); - #ifdef DEBUG - fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str); - #endif - } - g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow)); - (*bow) = NULL; - } - return 0; -} - -/*Removes leading and trailing whitespace, comments, and reduces - redundant whitespace down to one tab, makes an empty line an empty string.*/ -static void prettify_line(char *line) { - register char *look; - register char *write; - register int in_whitespace; - register int leading_whitespace; - for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) { -#ifdef DEBUG_2 - fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace); -#endif - if(*look == '#') { -#ifdef DEBUG_2 - fprintf(stderr, "comment\n"); -#endif - *write = '\0'; - break; - } - switch(*look) { - case ' ': - case '\n': - case '\t': -#ifdef DEBUG_2 - fprintf(stderr, "whitespace\n"); -#endif - if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t'; - in_whitespace=1; - break; - default: -#ifdef DEBUG_2 - fprintf(stderr, "default\n"); -#endif - *write++ = *look; - in_whitespace=leading_whitespace=0; - } - } - *write='\0'; - for(look=write=line; *look != '\0'; look++) { - switch(*look) { - case ' ': - case '\n': - case '\t': - if(*(look+1) == '\0') { - *look = '\0'; - } - } - } -} - -/*Error values: - * 0: success - * 1: failure malloc'ing / initializing mdb struct - * 2: failure opening file. - * 4: failure reading line. - * 8: warning reading line: no tab separator (line parsing error) - * 16: warning reading line: bad section declaration - * 32: warning reading line: unable to allocate material struct. - * 64: warning reading line: ignored line (unallocated material struct) - * 128: warning reading line: unable to allocate bowing struct - * 256: warning reading line: ignored line (unallocated bowing struct) - * 512: warning reading file: improper section detected (programming - * error) - *1024: warning reading file: no : separator in bowing materials - * description. - *2048: warning reading file: unable to read numeric value for property. - */ -struct matdb* read_matdb_dotcode(const GString *name, int* err) { -#ifdef DEBUG_2 - fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err); -#endif - *err=0; - struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb)); - if(mdb == NULL) {*err = 1; return NULL;} - - double *value; - if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) { - *err = 1; - free(mdb); - return NULL; - } - if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) { - *err = 1; - g_hash_table_unref(mdb->materials); - free(mdb); - return NULL; - } - struct matdb_material *mat = NULL; - struct matdb_bowing *bow = NULL; - /*Valid sections: - * 0 (no/global section) - * 1 (material) - * 2 (bow) - */ - int section=0; - int n; - char *line; - FILE *infile = fopen(name->str, "r"); - if(infile == NULL) { - g_hash_table_unref(mdb->materials); - g_hash_table_unref(mdb->bowings); - free(mdb); - *err=2; - return NULL; -#ifdef DEBUG_2 - }else{ - fprintf(stderr, "infile=%x\n", (unsigned int)infile); -#endif - } - int val; - while(!feof(infile)) { -#ifdef DEBUG - fprintf(stderr, "mat=%x(%s), bow=%x(%s:%s)\n", (unsigned int)mat, mat?mat->name->str:"", (unsigned int)bow, bow?bow->from->str:"", bow?bow->to->str:""); -#endif - line=NULL; - if((val = getline(&line, &n, infile)) == -1) { -#ifdef DEBUG_2 - fprintf(stderr, "getline returned %d\n", val); -#endif - if(!feof(infile)) *err = 4; - //fclose(infile); - break; - } -#ifdef DEBUG_2 - fprintf(stderr, "line=(%s)\n", line); -#endif - prettify_line(line); -#ifdef DEBUG - fprintf(stderr, "%d: prettified line=(%s)\n", section, line); -#endif - if(*line == '\0') { - free(line); - continue; - } - char *i = index(line, '\t'); - if(i == NULL) { - *err &= 8; - } - *i++ = '\0'; - /*At this point, we have line which stores the first word on the - line, and i which stores the second word on the line. - */ - char *to; - GHashTable *ht; -#ifdef DEBUG_2 - fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i); -#endif - /*If we have a material or bowing underway, save it off*/ - if(strcasecmp(line, "material") == 0) { - insert_into_matdb(mdb, &mat, &bow); - if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) { - *err &= 32; - } - if((mat->name = g_string_new(i)) == NULL) { - *err &= 32; - free(mat); - section=0; - continue; - } - if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) { - *err &= 32; - g_string_free(mat->name, TRUE); - free(bow); - section=0; - continue; - } -#ifdef DEBUG_2 - fprintf(stderr, "new material (%s):\n", i); -#endif - section=1; - }else if(strcasecmp(line, "bow") == 0) { - insert_into_matdb(mdb, &mat, &bow); - if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) { - *err &= 128; - } - if((to = index(i, ':')) == NULL) { - *err &= 1024; - free(bow); - section=0; - continue; - } - *to++ = '\0'; - /*Same trick as before, but i now stores the from material, - and to the to material - */ - if((bow->from = g_string_new(i)) == NULL) { - *err &= 128; - free(bow); - section=0; - continue; - } - if((bow->to = g_string_new(to)) == NULL) { - *err &= 128; - g_string_free(bow->from, TRUE); - free(bow); - section=0; - continue; - } - if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) { - *err &= 128; - g_string_free(bow->to, TRUE); - g_string_free(bow->from, TRUE); - free(bow); - section=0; - continue; - } -#ifdef DEBUG_2 - fprintf(stderr, "new bowing (%s:%s):\n", i, to); -#endif - section=2; - }else{ - #ifdef DEBUG - fprintf(stderr, "\t%d/%s\t", section, line); - #endif - /*Process a property.*/ - switch(section) { - case 1: - #ifdef DEBUG - fprintf(stderr, "(1)\t"); - #endif - ht = mat->properties; - break; - case 2: - #ifdef DEBUG - fprintf(stderr, "(2)\t"); - #endif - ht = bow->properties; - break; - default: - #ifdef DEBUG - fprintf(stderr, "(default)\t"); - #endif - *err &= 16; - section = 0; - } - if(section == 0) { - #ifdef DEBUG - fprintf(stderr, "section was 0\n"); - #endif - continue; - } - if((value = (double*)malloc(sizeof(double))) == NULL) { - *err &= 2048; - #ifdef DEBUG - fprintf(stderr, "malloc of value failed\n"); - #endif - continue; - } - int num; - if((num=sscanf(i, " %lg", value)) != 1) { - *err &= 2048; - free(value); - #ifdef DEBUG - fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num); - #endif - continue; - } - g_hash_table_insert(ht, g_strdup(line), value); -#ifdef DEBUG - fprintf(stderr, "%g(%s)\n", *value, line); -#endif - } - free(line); - line=i=to=NULL; - value=NULL; - } - fclose(infile); - insert_into_matdb(mdb, &mat, &bow); - return mdb; -} - diff --git a/matdb-dotcode.h b/matdb-dotcode.h deleted file mode 100644 index ebe4719..0000000 --- a/matdb-dotcode.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * matdb-dotcode: reads in Craig's Dotcode materials database. - - - - Copyright (C) 2008 Joseph Pingenot - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -*/ - -#ifndef MATDB_DOTCODE_H_ -#define MATDB_DOTCODE_H_ - -#include - -struct matdb* read_matdb_dotcode(const GString *name, int *err); - -#endif diff --git a/matdb.c b/matdb.c deleted file mode 100644 index 644eb40..0000000 --- a/matdb.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * matdb: generic materials database information. - - - - Copyright (C) 2008 Joseph Pingenot - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -*/ - -#include -#include -#include - -static void print_property(gpointer key, gpointer value, gpointer user_data) { - fprintf(stderr, "\t\t%s=%g:\n", (char*)key, *(double*)value); -} -static void print_inner_bowing(gpointer key, gpointer value, gpointer user_data) { - struct matdb_bowing *bowing = (struct matdb_bowing*)value; - fprintf(stderr, "\tbowing %s:%s[%s:%s]:\n", bowing->from->str, bowing->to->str, (char*)user_data, (char*)key); - g_hash_table_foreach(bowing->properties, &print_property, NULL); -} -static void print_material(gpointer key, gpointer value, gpointer user_data) { - struct matdb_material *mat = (struct matdb_material*)value; - fprintf(stderr, "\tmaterial %s(%s):\n", mat->name->str, (char*)key); - g_hash_table_foreach(mat->properties, &print_property, NULL); -} -static void print_bowing(gpointer key, gpointer value, gpointer user_data) { - GHashTable *ht = value; - g_hash_table_foreach(ht, &print_inner_bowing, key); -} - -void print_matdb(const struct matdb *mdb) { - fprintf(stderr, "matdb:\n"); - g_hash_table_foreach(mdb->materials, &print_material, NULL); - g_hash_table_foreach(mdb->bowings, &print_bowing, NULL); -} - -void destroy_material_gpointer(gpointer data) { - destroy_material((struct matdb_material *)data); -} -void destroy_bowing_gpointer(gpointer data) { - destroy_bowing((struct matdb_bowing *)data); -} -void destroy_material(struct matdb_material *mat) { - #ifdef DEBUG - fprintf(stderr, "destroy_material\n"); - #endif - g_string_free(mat->name, TRUE); - g_hash_table_unref(mat->properties); - free(mat); -} -void destroy_bowing(struct matdb_bowing *bow) { - #ifdef DEBUG - fprintf(stderr, "destroy_bowing\n"); - #endif - g_string_free(bow->from, TRUE); - g_string_free(bow->to, TRUE); - g_hash_table_unref(bow->properties); - free(bow); -} diff --git a/matdb.h b/matdb.h deleted file mode 100644 index 19747f8..0000000 --- a/matdb.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * matdb: generic materials database information. - - - - Copyright (C) 2008 Joseph Pingenot - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -*/ - -#ifndef MATDB_H_ -#define MATDB_H_ - -#include - -struct matdb_material { - GString *name; - GHashTable *properties; -}; - -struct matdb_bowing { - GString *from; - GString *to; - GHashTable *properties; -}; - -struct matdb { - GHashTable *materials; - GHashTable *bowings; -}; - -void print_matdb(const struct matdb *mdb); -void destroy_material_gpointer(gpointer data); -void destroy_bowing_gpointer(gpointer data); -void destroy_material(struct matdb_material *mat); -void destroy_bowing(struct matdb_bowing *bow); - -#endif diff --git a/matdb.txt b/matdb.txt deleted file mode 120000 index e69de29..0000000 diff --git a/scdataviz.c b/scdataviz.c deleted file mode 100644 index 812cd26..0000000 --- a/scdataviz.c +++ /dev/null @@ -1,183 +0,0 @@ -/* -** scdataviz.c -** -** Made by (Johnny Q. Hacker) -** Login -** -** Holds the SC graphing widget. - - - - Copyright (C) 2008 Joseph Pingenot - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -** Started on Thu Jul 17 11:03:27 2008 Johnny Q. Hacker -** Last update Thu Oct 8 19:13:57 2009 Johnny Q. Hacker -*/ - -#include -#include -#include -#include -#include - -#define DEBUG_SHOW_ONLY_BOWED - -struct xy_properties { - GString *xprop; - GString *yprop; - Graph *graph; - struct matdb *mdb; - struct matdb_material *mat; -}; - -static void lookup_xy(GHashTable* propts, GString* xprop, GString* yprop, double **x, double **y) { - *x=g_hash_table_lookup(propts, xprop->str); - *y=g_hash_table_lookup(propts, yprop->str); -} - -static void put_mat_in_graph(gpointer key, gpointer value, gpointer user_data) { - struct xy_properties *propmap = user_data; - struct matdb_material *mat = value; - if(!strcasecmp(mat->name->str, "vacuum")) return; - if(!strcasecmp(mat->name->str, "pvb")) return; - double *x, *y; - #ifdef DEBUG_ASSIGNMENT - fprintf(stderr, "put_mat_in_graph(%s) (x->%s, y->%s): ", (char*)key, propmap->xprop->str, propmap->yprop->str); - #endif - lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &x, &y); - if((x != NULL) && (y != NULL)) { - graph_add_point(propmap->graph, *x, *y, mat->name); - #ifdef DEBUG_ASSIGNMENT - fprintf(stderr, "added (x->%s=%g, y->%s=%g)\n", propmap->xprop->str, *x, propmap->yprop->str, *y); - }else{ - fprintf(stderr, "no such properties (x->%s, y->%s)\n", propmap->xprop->str, propmap->yprop->str); - #endif - } -} - -static void inner_link_materials(gpointer key, gpointer value, gpointer user_data) { - struct xy_properties *propmap = user_data; - struct matdb_material *mat = value; - if(!strcasecmp(mat->name->str, "vacuum")) return; - if(!strcasecmp(mat->name->str, "pvb")) return; - if(g_string_equal(mat->name, propmap->mat->name)) return; - struct graph_line *l = (struct graph_line *)malloc(sizeof(struct graph_line)); - if(l == NULL) return; - struct matdb_bowing *bow = NULL; - GHashTable *subtable; - double *p0_x, *p0_y, *p1_x, *p1_y, *p3_x, *p3_y; - lookup_xy(propmap->mat->properties, propmap->xprop, propmap->yprop, &p0_x, &p0_y); - lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &p3_x, &p3_y); -#ifdef DEBUG_ASSIGNMENT - fprintf(stderr, "%s:%s x=%s y=%s p0(%g,%g) p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, propmap->xprop->str, propmap->yprop->str, (p0_x)?*p0_x:0, (p0_y)?*p0_y:0, (p3_x)?*p3_x:0, (p3_y)?*p3_y:0); -#endif - if((p0_x != NULL) && (p0_y != NULL) && (p3_x != NULL) && (p3_y != NULL)) { - l->p0_x = *p0_x; - l->p0_y = *p0_y; - l->p3_x = *p3_x; - l->p3_y = *p3_y; - if((subtable = g_hash_table_lookup(propmap->mdb->bowings, propmap->mat->name->str)) == NULL) { - /*Try the other way 'round*/ - if((subtable = g_hash_table_lookup(propmap->mdb->bowings, mat->name->str) ) - != NULL) { - bow = g_hash_table_lookup(subtable, propmap->mat->name->str); - } - }else{ - bow = g_hash_table_lookup(subtable, mat->name->str); - } - if(bow != NULL) { - if((p1_x = g_hash_table_lookup(bow->properties, propmap->xprop->str)) != NULL) { - l->p1_x = *p1_x/2.0; - graph_bezier_quadratic_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x)); - }else{ - graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x)); - } - if((p1_y = g_hash_table_lookup(bow->properties, propmap->yprop->str)) != NULL) { - l->p1_y = *p1_y/2.0; - graph_bezier_quadratic_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y)); - }else{ - graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y)); - } - }else{ - #ifdef DEBUG_SHOW_ONLY_BOWED - free(l); - return; - #endif - graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x)); - graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y)); - } - #ifdef DEBUG_ASSIGNMENT - fprintf(stderr, "%s:%s p0(%g,%g) p1(%g,%g) p2(%g,%g), p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, l->p0_x, l->p0_y, l->p1_x, l->p1_y, l->p2_x, l->p2_y, l->p3_x, l->p3_y); - #endif - graph_add_graph_line(propmap->graph, l); - }else{ - free(l); - } -} - -static void link_materials(gpointer key, gpointer value, gpointer user_data) { - struct xy_properties *propmap = user_data; - struct matdb_material *mat = value; - if(!strcasecmp(mat->name->str, "vacuum")) return; - if(!strcasecmp(mat->name->str, "pvb")) return; - propmap->mat = mat; - g_hash_table_foreach(propmap->mdb->materials, &inner_link_materials, propmap); -} - -int main(int argc, char *argv[]) -{ - GtkWidget *window; - GtkWidget *graph; - GString *file = g_string_new("matdb.txt"); - int err=0; - struct matdb *mdb = read_matdb_dotcode(file, &err); - //fprintf(stderr, "read_matdb_dotcode(%s, %d)=%x", file->str, err, - //(int)mdb); - //fprintf(stderr, "err=%d\n", err); - //print_matdb(mdb); - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - graph = graph_widget_new(); - - struct xy_properties propmap; - propmap.xprop = g_string_new("a_lc"); - propmap.yprop = g_string_new("E_g_Gamma"); - propmap.graph = graph_widget_get_graph(GRAPH_WIDGET(graph)); - propmap.mdb = mdb; - g_hash_table_foreach(mdb->materials, &put_mat_in_graph, &propmap); - //graph_add_linear_connectors(propmap.graph); - g_hash_table_foreach(mdb->materials, &link_materials, &propmap); - graph_autoset_xaxis(propmap.graph, propmap.xprop); - graph_autoset_yaxis(propmap.graph, propmap.yprop); - - //Connect signals - g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); - - gtk_container_add(GTK_CONTAINER(window), graph); - /* - graph_add_point(graph_widget_get_graph(graph), 5, 3); - graph_add_point(graph_widget_get_graph(graph), 8, 12); - graph_add_point(graph_widget_get_graph(graph), 11, 48); - */ - - gtk_widget_show_all (window); - - gtk_main (); - - return 0; -} diff --git a/src/graph.c b/src/graph.c new file mode 100644 index 0000000..cd2b056 --- /dev/null +++ b/src/graph.c @@ -0,0 +1,242 @@ +/* +** Graph.c +** +** Made by (Johnny Q. Hacker) +** Login +** + + +Copyright (C) 2008 Joseph Pingenot + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + + +**Many thanks to Davyd Madeley for the excellent Cairo Tutorial +** at http://gnomejournal.org/article/34/writing-a--using-cairo-and-gtk28 + +** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker +** Last update Sun May 12 01:17:25 2002 Speed Blue +*/ + +#include +#include +#include +#include + +#ifdef DEBUG +#define DEBUG_AUTOAXIS +#endif + +G_DEFINE_TYPE(Graph, graph, G_TYPE_OBJECT); + +static void graph_class_init(GraphClass *klass) { + GObjectClass *gobject_klass; + gobject_klass = G_OBJECT_CLASS(klass); +} + +static void graph_init(Graph *graph) { + graph->symbol = CIRCLE; + graph->points = g_ptr_array_new(); + graph->lines = NULL; + graph->xaxis = graph->yaxis = NULL; +} + +Graph *graph_new(void) { + return g_object_new(GRAPH_TYPE, NULL); +} + +/*1 means you're stupid and passed NULL*/ +int graph_add_graph_point(Graph* graph, struct graph_point *pt) { + if(pt == NULL) return 1; + g_ptr_array_add(graph->points, pt); + if((graph->points->len == 1) && ((graph->lines == NULL) || (graph->lines->len == 0))) { + graph->maxx = graph->minx = pt->x; + graph->maxy = graph->miny = pt->y; + }else{ + if(pt->x > graph->maxx) graph->maxx = pt->x; + if(pt->x < graph->minx) graph->minx = pt->x; + if(pt->y > graph->maxy) graph->maxy = pt->y; + if(pt->y < graph->miny) graph->miny = pt->y; + } + return 0; +} + +/* + * + *1 means failed to allocate point + *NOTE: label is duplicated if not NULL (using g_strdup) + */ +int graph_add_point(Graph* graph, double x, double y, const GString *label) { + struct graph_point *pt = (struct graph_point*)malloc(sizeof(struct graph_point)); + if(pt == NULL) return 1; + pt->x = x; + pt->y = y; + pt->label = (label)?g_string_new(label->str):NULL; + graph_add_graph_point(graph, pt); + return 0; +} + +int graph_add_graph_line(Graph* graph, struct graph_line *l) { + if(l == NULL) return 1; + if(graph->lines == NULL) { + if((graph->lines = g_ptr_array_new()) == NULL) return 1; + } + g_ptr_array_add(graph->lines, l); + if((graph->points->len == 0) && + (graph->lines->len == 1)) { + graph->maxx = graph->minx = l->p0_x; + graph->maxy = graph->miny = l->p0_y; + }else{ + if(l->p0_x > graph->maxx) graph->maxx = l->p0_x; + if(l->p0_x < graph->minx) graph->minx = l->p0_x; + if(l->p0_y > graph->maxy) graph->maxy = l->p0_y; + if(l->p0_y < graph->miny) graph->miny = l->p0_y; + } + if(l->p3_x > graph->maxx) graph->maxx = l->p3_x; + if(l->p3_x < graph->minx) graph->minx = l->p3_x; + if(l->p3_y > graph->maxy) graph->maxy = l->p3_y; + if(l->p3_y < graph->miny) graph->miny = l->p3_y; + return 0; +} + + +int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y) { + #ifdef DEBUG + fprintf(stderr, "graph_add_line(%d, p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", (unsigned int) graph, p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y); + #endif + struct graph_line *l; + if((l=(struct graph_line*)malloc(sizeof(struct graph_line))) == NULL) return 2; + l->p0_x=p0_x; + l->p0_y=p0_y; + l->p1_x=p1_x; + l->p1_y=p1_y; + l->p2_x=p2_x; + l->p2_y=p2_y; + l->p3_x=p3_x; + l->p3_y=p3_y; + return graph_add_graph_line(graph, l); +} + +struct cxt { + Graph *graph; + struct graph_point *p0; +}; + +static void linear_interpolate(gpointer data, gpointer user_data) { + struct cxt *cxt = user_data; + struct graph_point *p3 = data; + if(cxt->p0 != NULL) { + double p1_x = (p3->x + 2*cxt->p0->x)/3.0; + double p1_y = (p3->y + 2*cxt->p0->y)/3.0; + double p2_x = (2*p3->x + cxt->p0->x)/3.0; + double p2_y = (2*p3->y + cxt->p0->y)/3.0; + graph_add_line(cxt->graph, cxt->p0->x, cxt->p0->y, p1_x, p1_y, p2_x, p2_y, p3->x, p3->y); + } + cxt->p0 = p3; +} + +void graph_add_linear_connectors(Graph* graph) { + struct cxt cxt; + cxt.graph = graph; + cxt.p0 = NULL; + g_ptr_array_foreach(graph->points, &linear_interpolate, &cxt); +} + +void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2) { + *x1 = (x3 + 2.0*x0)/3.0; + *x2 = (2.0*x3 + x0)/3.0; +} + +void graph_bezier_linear_to_quadratic(double x0, double x3, double *x1) { + *x1 = (x3 + x0)/2.0; +} + +void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2) { + *x2 = (x3-2.0*(*x1))/3.0; + *x1 = (x0-2.0*(*x1))/3.0; +} + +void graph_set_xaxis(Graph *g, struct graph_axis *axis) { + if(g->xaxis != NULL) { + free(g->xaxis); + } + g->xaxis=axis; +} +void graph_set_yaxis(Graph *g, struct graph_axis *axis) { + if(g->yaxis != NULL) { + free(g->yaxis); + } + g->yaxis=axis; +} + +struct graph_axis* autoset_axis(Graph* g, GString* title, double min, double max) { + struct graph_axis *axis; + double range_mag; + double start_mag; + double stop_mag; + int i, j; + if(g->points->len == 0) { + return NULL; + } + if((axis=(struct graph_axis *)malloc(sizeof(struct graph_axis))) == NULL) { + return NULL; + } + if(g->points->len == 1) { + axis->major=1; + axis->minor=0; + axis->subminor=0; + axis->major_start=min; + axis->major_step=max; + }else{ + range_mag = logb(max - min); + if(min == 0) + start_mag = 0; + else + start_mag = copysign(pow(10, floor(log10(min))), min); + if(max == 0) + stop_mag = 0; + else + stop_mag = copysign(pow(10, ceil(log10(max))), max); + for(i=1; i<9; i++) { + if(i*start_mag > min) break; + } + i--; + for(j=10; j>1; j--) { + if(j*(stop_mag/10) < max) break; + } + j++; + axis->major=10; + axis->minor=1; + axis->subminor=4; + axis->major_start=i*start_mag; + axis->major_step=(j*(stop_mag/10) - axis->major_start)/(axis->major); + } + axis->title=g_string_new(title->str); + #ifdef DEBUG_AUTOAXIS + fprintf(stderr, "graph_autoset_xaxis: xmin=%g, log10(xmin)=%g, floor=%g, pow=%g round=%g\n", min, log10(min), floor(log10(min)), pow(10, floor(log10(min))), round(pow(10, floor(log10(min))))); + fprintf(stderr, "graph_autoset_xaxis: xmax=%g, log10(xmax)=%g, floor=%g, pow=%g round=%g\n", max, log10(max), floor(log10(max)), pow(10, floor(log10(max))), round(pow(10, floor(log10(max))))); + fprintf(stderr, "graph_autoset_xaxis: xmin=%g,max=%g start_mag=%g, stop_mag=%g range_mag=%g\n", min, max, start_mag, stop_mag, range_mag); + #endif + return axis; +} + +int graph_autoset_xaxis(Graph *g, GString *title) { + graph_set_xaxis(g, autoset_axis(g, title, g->minx, g->maxx)); + return 0; +} + +int graph_autoset_yaxis(Graph *g, GString *title) { + graph_set_yaxis(g, autoset_axis(g, title, g->miny, g->maxy)); + return 0; +} diff --git a/src/graph.h b/src/graph.h new file mode 100644 index 0000000..31d441f --- /dev/null +++ b/src/graph.h @@ -0,0 +1,107 @@ +/* +** Graph.h +** +** Made by Johnny Q. Hacker +** Login +** + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker +** Last update Thu Jul 17 10:51:32 2008 Johnny Q. Hacker +*/ + +#ifndef GRAPHCLASS_H_ +#define GRAPHCLASS_H_ + +#include + +typedef enum {SQUARE, CIRCLE, STAR, PLUS, MINUS, CROSS} graph_symbol; + +struct graph_point { + double x; + double y; + GString *label; +}; + +/*Bezier line*/ +struct graph_line { + /*First point*/ + double p0_x; + double p0_y; + /*Control pts*/ + double p1_x; + double p1_y; + double p2_x; + double p2_y; + /*End point*/ + double p3_x; + double p3_y; +}; + +struct graph_axis { + double major_start; + double major_step; + int major; + int minor; + int subminor; + GString *title; +}; + +typedef struct _Graph { + GObject parent_instance; + /*Array of n_points sets of x,y coords*/ + GPtrArray *points; + /*This draws all of the lines (generally between points)*/ + GPtrArray *lines; + double maxx; + double minx; + double maxy; + double miny; + graph_symbol symbol; + struct graph_axis *xaxis; + struct graph_axis *yaxis; +} Graph; + +typedef struct _GraphClass { + GObjectClass parent_class; +} GraphClass; + +#define GRAPH_TYPE (graph_get_type()) +#define GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_TYPE, Graph)) +#define GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH, GraphClass)) +#define IS_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_TYPE)) +#define IS_GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_CLASS_TYPE)) +#define GRAPH_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH, GraphClass)) + +Graph *graph_new(void); +int graph_add_point(Graph* graph, double x, double y, const GString *label); +int graph_add_graph_point(Graph* graph, struct graph_point *pt); +int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y); +int graph_add_graph_line(Graph* graph, struct graph_line *l); +void graph_add_linear_connectors(Graph* graph); +/*Provide x0, x3; x1 and x2 will be set*/ +void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2); +/*Provide x0, x1, x2. x1 and x2 will be set appropriately.*/ +void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2); +void graph_set_xaxis(Graph *g, struct graph_axis *axis); +void graph_set_yaxis(Graph *g, struct graph_axis *axis); +int graph_autoset_xaxis(Graph *g, GString *title); +int graph_autoset_yaxis(Graph *g, GString *title); + + + +#endif /* !GRAPHCLASS_H_ */ diff --git a/src/graphwidget.c b/src/graphwidget.c new file mode 100644 index 0000000..beba3c9 --- /dev/null +++ b/src/graphwidget.c @@ -0,0 +1,252 @@ +/* +** Graph.c +** +** Made by (Johnny Q. Hacker) +** Login +** + + + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +**Many thanks to Davyd Madeley for the excellent Cairo Widget Tutorial +** at http://gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28 + +** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker +** Last update Thu Oct 8 17:13:50 2009 Johnny Q. Hacker +*/ + +#include +#include + +G_DEFINE_TYPE(GraphWidget, graph_widget, GTK_TYPE_DRAWING_AREA); + +#define INSET_PERCENT 0.1 +#define TITLE_PERCENT 0.15 +#define DEBUG_DRAW_AXIS + +struct drawing_context { + GtkWidget *widget; + cairo_t *cr; + double radius; + double xoffset; + double yoffset; + double xscaling; + double yscaling; + /*Semi-normalized maxima*/ + double xmax; + double ymax; + cairo_matrix_t data_scale; + cairo_matrix_t data_xlat; +}; + +static void draw_point(gpointer data, gpointer user_data) { + struct drawing_context *cxt = user_data; + struct graph_point *pt = data; + double x = (pt->x + cxt->xoffset)*cxt->xscaling; + double y = (pt->y + cxt->yoffset)*cxt->yscaling; + cairo_move_to(cxt->cr, x, y); + cairo_arc(cxt->cr, x, y, cxt->radius, 0, 2*M_PI); + if(pt->label != NULL) { + cairo_save(cxt->cr); + cairo_scale(cxt->cr, 1, -1); + cairo_show_text(cxt->cr, pt->label->str); + cairo_restore(cxt->cr); + } +} + +static void draw_lines(gpointer data, gpointer user_data) { + struct drawing_context *cxt = user_data; + struct graph_line *l = data; + double p0_x = (l->p0_x + cxt->xoffset)*cxt->xscaling; + double p0_y = (l->p0_y + cxt->yoffset)*cxt->yscaling; + double p1_x = (l->p1_x + cxt->xoffset)*cxt->xscaling; + double p1_y = (l->p1_y + cxt->yoffset)*cxt->yscaling; + double p2_x = (l->p2_x + cxt->xoffset)*cxt->xscaling; + double p2_y = (l->p2_y + cxt->yoffset)*cxt->yscaling; + double p3_x = (l->p3_x + cxt->xoffset)*cxt->xscaling; + double p3_y = (l->p3_y + cxt->yoffset)*cxt->yscaling; + #ifdef DEBUG_DRAW + fprintf(stderr, "draw_lines: p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y); + #endif + cairo_move_to(cxt->cr, p0_x, p0_y); + cairo_curve_to(cxt->cr, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y); +} + +static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis, double scaling, double offset, double max) { + #ifdef DEBUG_DRAW_AXIS + fprintf(stderr, "draw_axis; major_start=%g, major_step=%g, >major=%d, minor=%d, subminor=%d, label=%s\n", axis->major_start, axis->major_step, axis->major, axis->minor, axis->subminor, axis->title->str); + #endif + cairo_move_to(cxt->cr, 0, 0); + cairo_line_to(cxt->cr, max, 0); + register int i, j, k; + register double pos, mpos, smpos; + for(i=0; imajor; i++) { + pos=i*axis->major_step + axis->major_start; + cairo_move_to(cxt->cr, (pos + offset)*scaling, 0); + cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05); + for(k=0; ksubminor; k++) { + smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + pos; + cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0); + cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125); + } + for(j=0; jminor; j++) { + mpos=(j+1)*(axis->major_step/(axis->minor+1)) + pos; + cairo_move_to(cxt->cr, (mpos + offset)*scaling, 0); + cairo_line_to(cxt->cr, (mpos + offset)*scaling, 0.025); + for(k=0; ksubminor; k++) { + smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + mpos; + cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0); + cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125); + } + } + } + pos=i*axis->major_step + axis->major_start; + cairo_move_to(cxt->cr, (pos + offset)*scaling, 0); + cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05); +} + +static void draw(GtkWidget *graph, cairo_t *cr) { + struct drawing_context cxt; + GraphWidget *gw = GRAPH_WIDGET(graph); + #ifdef DEBUG_DRAW + fprintf(stderr, "draw(%d, %d)\n", (int)graph, (int)cr); + fprintf(stderr, "allocation.x=%d, allocation.y=%d, allocation.height=%d, allocation.width=%d\n", graph->allocation.x, graph->allocation.y, graph->allocation.height, graph->allocation.width); + #endif + double x0=graph->allocation.x; + double y0=graph->allocation.y; + double height=graph->allocation.height; + double width=graph->allocation.width; + double minx = gw->graph->minx; + double maxx = gw->graph->maxx; + double miny = gw->graph->miny; + double maxy = gw->graph->maxy; + if(gw->graph->xaxis != NULL) { + minx = gw->graph->xaxis->major_start; + maxx = gw->graph->xaxis->major_start + gw->graph->xaxis->major_step*gw->graph->xaxis->major; + } + if(gw->graph->yaxis != NULL) { + miny = gw->graph->yaxis->major_start; + maxy = gw->graph->yaxis->major_start + gw->graph->yaxis->major_step*gw->graph->yaxis->major; + } + cxt.widget = graph; + cxt.cr = cr; + cxt.radius = 0.01; + /*Set up our semi-normalized scaling. The shortest direction range + [0, 1]; the other range depends upon the relative sizes.*/ + double effective_height = height; + double effective_width = width; + double inset, axis_inset; + if((INSET_PERCENT > 0) && (INSET_PERCENT < 1.0)) { + inset = ((effective_height > effective_width)?effective_width:effective_height)*INSET_PERCENT; + effective_height -= inset; + effective_width -= inset; + } + if((gw->graph->xaxis != NULL) && (gw->graph->yaxis != NULL)) { + /*key off the smaller size.*/ + axis_inset = ((effective_height > effective_width)?effective_width:effective_height)*TITLE_PERCENT; + effective_height -= axis_inset; + effective_width -= axis_inset; + }else if(gw->graph->xaxis != NULL) { + effective_height -= effective_height*TITLE_PERCENT; + }else if(gw->graph->yaxis != NULL) { + effective_width -= effective_width*TITLE_PERCENT; + } + if(effective_width > effective_height) { + cxt.xmax = effective_width/effective_height; + cxt.ymax = 1.0; + }else{ + cxt.xmax = 1.0; + cxt.ymax = effective_height/effective_width; + } + /*Convert from data space to the semi-normalized space*/ + double xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(maxx-minx)); + double yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(maxy-miny)); + double xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx); + double yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny); + /*Finish up our context information.*/ + cxt.xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(((maxx - minx)==0)?1:(maxx-minx))); + cxt.yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(((maxy - miny)==0)?1:(maxy-miny))); + cxt.xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx); + cxt.yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny); + cairo_matrix_translate(&(cxt.data_xlat), xoffset, yoffset); + cairo_matrix_scale(&(cxt.data_scale), xscaling, yscaling); + #ifdef DEBUG + fprintf(stderr, "minx=%g, maxx=%g, miny=%g, maxy=%g, xscaling=%g, yscaling=%g, xoffset=%g, yoffset=%g\n", minx, maxx, miny, maxy, cxt.xscaling, cxt.yscaling, cxt.xoffset, cxt.yoffset); + fprintf(stderr, "x0=%g, y0=%g, width=%g, height=%g\n", x0, y0, height, width); + fprintf(stderr, "translate=(%g, %g)\n", x0 + ((width>height)?(width-height)/2.0:0), y0+((width > height)?height:width) + ((height>width)?(height-width)/2.0:0)); + #endif + double offset_height = ((width>=height)?height*INSET_PERCENT:0);; + double offset_width = ((height>=width)?width*INSET_PERCENT:0); + double inset_height = height - offset_height; + double inset_width = width - offset_width; + cairo_save(cr); + cairo_translate(cr, x0 + (width - effective_width) - inset/2, y0 + effective_height + inset/2); + cairo_scale(cr, effective_width/cxt.xmax, -effective_height/cxt.ymax); + cairo_set_line_width(cr, 0.005); + cairo_select_font_face (cr, "Georgia", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size (cr, 0.05); + if(gw->graph->lines != NULL) { + cairo_set_source_rgba(cr, 0, 0, 0, 0.25); + g_ptr_array_foreach(gw->graph->lines, &draw_lines, (gpointer)&cxt); + cairo_stroke(cr); + } + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_fill_preserve(cr); + cairo_set_source_rgb(cr, 0, 0, 0); + g_ptr_array_foreach(gw->graph->points, &draw_point, (gpointer)&cxt); + if(gw->graph->xaxis != NULL) + draw_axis(&cxt, gw->graph->xaxis, cxt.xscaling, cxt.xoffset, cxt.xmax); + if(gw->graph->yaxis != NULL) { + cairo_save(cr); + cairo_matrix_t matrix = { .xx=0, .xy = 1, .x0 = 0, .yx = 1, .yy = 0, .y0 = 0 }; + cairo_transform(cr, &matrix); + draw_axis(&cxt, gw->graph->yaxis, cxt.yscaling, cxt.yoffset, cxt.ymax); + cairo_restore(cr); + } + cairo_stroke(cr); + cairo_restore(cr); +} + +static gboolean graph_widget_expose(GtkWidget *graph, GdkEventExpose *event) { + cairo_t *cr = gdk_cairo_create(graph->window); + cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height); + cairo_clip(cr); + draw(graph, cr); + cairo_destroy(cr); + return FALSE; +} + +static void graph_widget_class_init(GraphWidgetClass *klass) { + GtkWidgetClass *widget_class; + widget_class = GTK_WIDGET_CLASS(klass); + widget_class->expose_event = graph_widget_expose; +} + +static void graph_widget_init(GraphWidget *graph) { + /*Get a graph.*/ + graph->graph = graph_new(); +} + +GtkWidget *graph_widget_new(void) { + return g_object_new(GRAPH_WIDGET_TYPE, NULL); +} + +Graph* graph_widget_get_graph(GraphWidget* gw) { + return gw->graph; +} + diff --git a/src/graphwidget.h b/src/graphwidget.h new file mode 100644 index 0000000..cb2e390 --- /dev/null +++ b/src/graphwidget.h @@ -0,0 +1,55 @@ +/* +** Graph.h +** +** Made by Johnny Q. Hacker +** Login +** + + + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker +** Last update Thu Oct 8 14:28:34 2009 Johnny Q. Hacker +*/ + +#ifndef GRAPHWIDGET_H_ +#define GRAPHWIDGET_H_ + +#include +#include + +typedef struct _GraphWidget { + GtkDrawingArea parent_instance; + Graph *graph; +} GraphWidget; + +typedef struct _GraphWidgetClass { + GtkDrawingAreaClass parent_class; +} GraphWidgetClass; + +#define GRAPH_WIDGET_TYPE (graph_widget_get_type()) +#define GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_WIDGET_TYPE, GraphWidget)) +#define GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH_WIDGET, GraphWidgetClass)) +#define IS_GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_WIDGET_TYPE)) +#define IS_GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_WIDGET_CLASS_TYPE)) +#define GRAPH_WIDGET_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH_WIDGET, GraphWidgetClass)) + +GtkWidget* graph_widget_new(void); + +Graph* graph_widget_get_graph(GraphWidget* gw); + +#endif /* !GRAPHWIDGET_H_ */ diff --git a/src/matdb-dotcode.c b/src/matdb-dotcode.c new file mode 100644 index 0000000..df195fb --- /dev/null +++ b/src/matdb-dotcode.c @@ -0,0 +1,346 @@ +/* + * matdb-dotcode: reads in Craig's Dotcode materials database. + + + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +*/ + +#include +#define _GNU_SOURCE +#include +#include +#include + +#ifdef DEBUG +#undef DEBUG +#endif +#ifdef DEBUG_2 +#undef DEBUG_2 +#endif + +/*Functions to be used by the hash.*/ +static void destroy_string(gpointer data) { + free((char*)data); +} +static void destroy_double(gpointer data){ + free((double*)data); +} +static void destroy_inner_bowhash(gpointer data) { + g_hash_table_unref(data); +} + +int insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) { + if((*mat) != NULL) { +#ifdef DEBUG + fprintf(stderr, "inserting material %s\n", (*mat)->name->str); +#endif + g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat)); + (*mat) = NULL; + } + if((*bow) != NULL) { +#ifdef DEBUG + fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str); +#endif + /*Inner table*/ + GHashTable *it; + if((it=g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) { + if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) { + (*bow) = NULL; + return 1; + } + g_hash_table_insert(mdb->bowings, (*bow)->from->str, it); + #ifdef DEBUG + fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str); + #endif + } + g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow)); + (*bow) = NULL; + } + return 0; +} + +/*Removes leading and trailing whitespace, comments, and reduces + redundant whitespace down to one tab, makes an empty line an empty string.*/ +static void prettify_line(char *line) { + register char *look; + register char *write; + register int in_whitespace; + register int leading_whitespace; + for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) { +#ifdef DEBUG_2 + fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace); +#endif + if(*look == '#') { +#ifdef DEBUG_2 + fprintf(stderr, "comment\n"); +#endif + *write = '\0'; + break; + } + switch(*look) { + case ' ': + case '\n': + case '\t': +#ifdef DEBUG_2 + fprintf(stderr, "whitespace\n"); +#endif + if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t'; + in_whitespace=1; + break; + default: +#ifdef DEBUG_2 + fprintf(stderr, "default\n"); +#endif + *write++ = *look; + in_whitespace=leading_whitespace=0; + } + } + *write='\0'; + for(look=write=line; *look != '\0'; look++) { + switch(*look) { + case ' ': + case '\n': + case '\t': + if(*(look+1) == '\0') { + *look = '\0'; + } + } + } +} + +/*Error values: + * 0: success + * 1: failure malloc'ing / initializing mdb struct + * 2: failure opening file. + * 4: failure reading line. + * 8: warning reading line: no tab separator (line parsing error) + * 16: warning reading line: bad section declaration + * 32: warning reading line: unable to allocate material struct. + * 64: warning reading line: ignored line (unallocated material struct) + * 128: warning reading line: unable to allocate bowing struct + * 256: warning reading line: ignored line (unallocated bowing struct) + * 512: warning reading file: improper section detected (programming + * error) + *1024: warning reading file: no : separator in bowing materials + * description. + *2048: warning reading file: unable to read numeric value for property. + */ +struct matdb* read_matdb_dotcode(const GString *name, int* err) { +#ifdef DEBUG_2 + fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err); +#endif + *err=0; + struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb)); + if(mdb == NULL) {*err = 1; return NULL;} + + double *value; + if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) { + *err = 1; + free(mdb); + return NULL; + } + if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) { + *err = 1; + g_hash_table_unref(mdb->materials); + free(mdb); + return NULL; + } + struct matdb_material *mat = NULL; + struct matdb_bowing *bow = NULL; + /*Valid sections: + * 0 (no/global section) + * 1 (material) + * 2 (bow) + */ + int section=0; + int n; + char *line; + FILE *infile = fopen(name->str, "r"); + if(infile == NULL) { + g_hash_table_unref(mdb->materials); + g_hash_table_unref(mdb->bowings); + free(mdb); + *err=2; + return NULL; +#ifdef DEBUG_2 + }else{ + fprintf(stderr, "infile=%x\n", (unsigned int)infile); +#endif + } + int val; + while(!feof(infile)) { +#ifdef DEBUG + fprintf(stderr, "mat=%x(%s), bow=%x(%s:%s)\n", (unsigned int)mat, mat?mat->name->str:"", (unsigned int)bow, bow?bow->from->str:"", bow?bow->to->str:""); +#endif + line=NULL; + if((val = getline(&line, &n, infile)) == -1) { +#ifdef DEBUG_2 + fprintf(stderr, "getline returned %d\n", val); +#endif + if(!feof(infile)) *err = 4; + //fclose(infile); + break; + } +#ifdef DEBUG_2 + fprintf(stderr, "line=(%s)\n", line); +#endif + prettify_line(line); +#ifdef DEBUG + fprintf(stderr, "%d: prettified line=(%s)\n", section, line); +#endif + if(*line == '\0') { + free(line); + continue; + } + char *i = index(line, '\t'); + if(i == NULL) { + *err &= 8; + } + *i++ = '\0'; + /*At this point, we have line which stores the first word on the + line, and i which stores the second word on the line. + */ + char *to; + GHashTable *ht; +#ifdef DEBUG_2 + fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i); +#endif + /*If we have a material or bowing underway, save it off*/ + if(strcasecmp(line, "material") == 0) { + insert_into_matdb(mdb, &mat, &bow); + if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) { + *err &= 32; + } + if((mat->name = g_string_new(i)) == NULL) { + *err &= 32; + free(mat); + section=0; + continue; + } + if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) { + *err &= 32; + g_string_free(mat->name, TRUE); + free(bow); + section=0; + continue; + } +#ifdef DEBUG_2 + fprintf(stderr, "new material (%s):\n", i); +#endif + section=1; + }else if(strcasecmp(line, "bow") == 0) { + insert_into_matdb(mdb, &mat, &bow); + if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) { + *err &= 128; + } + if((to = index(i, ':')) == NULL) { + *err &= 1024; + free(bow); + section=0; + continue; + } + *to++ = '\0'; + /*Same trick as before, but i now stores the from material, + and to the to material + */ + if((bow->from = g_string_new(i)) == NULL) { + *err &= 128; + free(bow); + section=0; + continue; + } + if((bow->to = g_string_new(to)) == NULL) { + *err &= 128; + g_string_free(bow->from, TRUE); + free(bow); + section=0; + continue; + } + if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) { + *err &= 128; + g_string_free(bow->to, TRUE); + g_string_free(bow->from, TRUE); + free(bow); + section=0; + continue; + } +#ifdef DEBUG_2 + fprintf(stderr, "new bowing (%s:%s):\n", i, to); +#endif + section=2; + }else{ + #ifdef DEBUG + fprintf(stderr, "\t%d/%s\t", section, line); + #endif + /*Process a property.*/ + switch(section) { + case 1: + #ifdef DEBUG + fprintf(stderr, "(1)\t"); + #endif + ht = mat->properties; + break; + case 2: + #ifdef DEBUG + fprintf(stderr, "(2)\t"); + #endif + ht = bow->properties; + break; + default: + #ifdef DEBUG + fprintf(stderr, "(default)\t"); + #endif + *err &= 16; + section = 0; + } + if(section == 0) { + #ifdef DEBUG + fprintf(stderr, "section was 0\n"); + #endif + continue; + } + if((value = (double*)malloc(sizeof(double))) == NULL) { + *err &= 2048; + #ifdef DEBUG + fprintf(stderr, "malloc of value failed\n"); + #endif + continue; + } + int num; + if((num=sscanf(i, " %lg", value)) != 1) { + *err &= 2048; + free(value); + #ifdef DEBUG + fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num); + #endif + continue; + } + g_hash_table_insert(ht, g_strdup(line), value); +#ifdef DEBUG + fprintf(stderr, "%g(%s)\n", *value, line); +#endif + } + free(line); + line=i=to=NULL; + value=NULL; + } + fclose(infile); + insert_into_matdb(mdb, &mat, &bow); + return mdb; +} + diff --git a/src/matdb-dotcode.h b/src/matdb-dotcode.h new file mode 100644 index 0000000..ebe4719 --- /dev/null +++ b/src/matdb-dotcode.h @@ -0,0 +1,30 @@ +/* + * matdb-dotcode: reads in Craig's Dotcode materials database. + + + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +*/ + +#ifndef MATDB_DOTCODE_H_ +#define MATDB_DOTCODE_H_ + +#include + +struct matdb* read_matdb_dotcode(const GString *name, int *err); + +#endif diff --git a/src/matdb.c b/src/matdb.c new file mode 100644 index 0000000..644eb40 --- /dev/null +++ b/src/matdb.c @@ -0,0 +1,73 @@ +/* + * matdb: generic materials database information. + + + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +*/ + +#include +#include +#include + +static void print_property(gpointer key, gpointer value, gpointer user_data) { + fprintf(stderr, "\t\t%s=%g:\n", (char*)key, *(double*)value); +} +static void print_inner_bowing(gpointer key, gpointer value, gpointer user_data) { + struct matdb_bowing *bowing = (struct matdb_bowing*)value; + fprintf(stderr, "\tbowing %s:%s[%s:%s]:\n", bowing->from->str, bowing->to->str, (char*)user_data, (char*)key); + g_hash_table_foreach(bowing->properties, &print_property, NULL); +} +static void print_material(gpointer key, gpointer value, gpointer user_data) { + struct matdb_material *mat = (struct matdb_material*)value; + fprintf(stderr, "\tmaterial %s(%s):\n", mat->name->str, (char*)key); + g_hash_table_foreach(mat->properties, &print_property, NULL); +} +static void print_bowing(gpointer key, gpointer value, gpointer user_data) { + GHashTable *ht = value; + g_hash_table_foreach(ht, &print_inner_bowing, key); +} + +void print_matdb(const struct matdb *mdb) { + fprintf(stderr, "matdb:\n"); + g_hash_table_foreach(mdb->materials, &print_material, NULL); + g_hash_table_foreach(mdb->bowings, &print_bowing, NULL); +} + +void destroy_material_gpointer(gpointer data) { + destroy_material((struct matdb_material *)data); +} +void destroy_bowing_gpointer(gpointer data) { + destroy_bowing((struct matdb_bowing *)data); +} +void destroy_material(struct matdb_material *mat) { + #ifdef DEBUG + fprintf(stderr, "destroy_material\n"); + #endif + g_string_free(mat->name, TRUE); + g_hash_table_unref(mat->properties); + free(mat); +} +void destroy_bowing(struct matdb_bowing *bow) { + #ifdef DEBUG + fprintf(stderr, "destroy_bowing\n"); + #endif + g_string_free(bow->from, TRUE); + g_string_free(bow->to, TRUE); + g_hash_table_unref(bow->properties); + free(bow); +} diff --git a/src/matdb.h b/src/matdb.h new file mode 100644 index 0000000..19747f8 --- /dev/null +++ b/src/matdb.h @@ -0,0 +1,50 @@ +/* + * matdb: generic materials database information. + + + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +*/ + +#ifndef MATDB_H_ +#define MATDB_H_ + +#include + +struct matdb_material { + GString *name; + GHashTable *properties; +}; + +struct matdb_bowing { + GString *from; + GString *to; + GHashTable *properties; +}; + +struct matdb { + GHashTable *materials; + GHashTable *bowings; +}; + +void print_matdb(const struct matdb *mdb); +void destroy_material_gpointer(gpointer data); +void destroy_bowing_gpointer(gpointer data); +void destroy_material(struct matdb_material *mat); +void destroy_bowing(struct matdb_bowing *bow); + +#endif diff --git a/src/scdataviz.c b/src/scdataviz.c new file mode 100644 index 0000000..812cd26 --- /dev/null +++ b/src/scdataviz.c @@ -0,0 +1,183 @@ +/* +** scdataviz.c +** +** Made by (Johnny Q. Hacker) +** Login +** +** Holds the SC graphing widget. + + + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +** Started on Thu Jul 17 11:03:27 2008 Johnny Q. Hacker +** Last update Thu Oct 8 19:13:57 2009 Johnny Q. Hacker +*/ + +#include +#include +#include +#include +#include + +#define DEBUG_SHOW_ONLY_BOWED + +struct xy_properties { + GString *xprop; + GString *yprop; + Graph *graph; + struct matdb *mdb; + struct matdb_material *mat; +}; + +static void lookup_xy(GHashTable* propts, GString* xprop, GString* yprop, double **x, double **y) { + *x=g_hash_table_lookup(propts, xprop->str); + *y=g_hash_table_lookup(propts, yprop->str); +} + +static void put_mat_in_graph(gpointer key, gpointer value, gpointer user_data) { + struct xy_properties *propmap = user_data; + struct matdb_material *mat = value; + if(!strcasecmp(mat->name->str, "vacuum")) return; + if(!strcasecmp(mat->name->str, "pvb")) return; + double *x, *y; + #ifdef DEBUG_ASSIGNMENT + fprintf(stderr, "put_mat_in_graph(%s) (x->%s, y->%s): ", (char*)key, propmap->xprop->str, propmap->yprop->str); + #endif + lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &x, &y); + if((x != NULL) && (y != NULL)) { + graph_add_point(propmap->graph, *x, *y, mat->name); + #ifdef DEBUG_ASSIGNMENT + fprintf(stderr, "added (x->%s=%g, y->%s=%g)\n", propmap->xprop->str, *x, propmap->yprop->str, *y); + }else{ + fprintf(stderr, "no such properties (x->%s, y->%s)\n", propmap->xprop->str, propmap->yprop->str); + #endif + } +} + +static void inner_link_materials(gpointer key, gpointer value, gpointer user_data) { + struct xy_properties *propmap = user_data; + struct matdb_material *mat = value; + if(!strcasecmp(mat->name->str, "vacuum")) return; + if(!strcasecmp(mat->name->str, "pvb")) return; + if(g_string_equal(mat->name, propmap->mat->name)) return; + struct graph_line *l = (struct graph_line *)malloc(sizeof(struct graph_line)); + if(l == NULL) return; + struct matdb_bowing *bow = NULL; + GHashTable *subtable; + double *p0_x, *p0_y, *p1_x, *p1_y, *p3_x, *p3_y; + lookup_xy(propmap->mat->properties, propmap->xprop, propmap->yprop, &p0_x, &p0_y); + lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &p3_x, &p3_y); +#ifdef DEBUG_ASSIGNMENT + fprintf(stderr, "%s:%s x=%s y=%s p0(%g,%g) p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, propmap->xprop->str, propmap->yprop->str, (p0_x)?*p0_x:0, (p0_y)?*p0_y:0, (p3_x)?*p3_x:0, (p3_y)?*p3_y:0); +#endif + if((p0_x != NULL) && (p0_y != NULL) && (p3_x != NULL) && (p3_y != NULL)) { + l->p0_x = *p0_x; + l->p0_y = *p0_y; + l->p3_x = *p3_x; + l->p3_y = *p3_y; + if((subtable = g_hash_table_lookup(propmap->mdb->bowings, propmap->mat->name->str)) == NULL) { + /*Try the other way 'round*/ + if((subtable = g_hash_table_lookup(propmap->mdb->bowings, mat->name->str) ) + != NULL) { + bow = g_hash_table_lookup(subtable, propmap->mat->name->str); + } + }else{ + bow = g_hash_table_lookup(subtable, mat->name->str); + } + if(bow != NULL) { + if((p1_x = g_hash_table_lookup(bow->properties, propmap->xprop->str)) != NULL) { + l->p1_x = *p1_x/2.0; + graph_bezier_quadratic_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x)); + }else{ + graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x)); + } + if((p1_y = g_hash_table_lookup(bow->properties, propmap->yprop->str)) != NULL) { + l->p1_y = *p1_y/2.0; + graph_bezier_quadratic_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y)); + }else{ + graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y)); + } + }else{ + #ifdef DEBUG_SHOW_ONLY_BOWED + free(l); + return; + #endif + graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x)); + graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y)); + } + #ifdef DEBUG_ASSIGNMENT + fprintf(stderr, "%s:%s p0(%g,%g) p1(%g,%g) p2(%g,%g), p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, l->p0_x, l->p0_y, l->p1_x, l->p1_y, l->p2_x, l->p2_y, l->p3_x, l->p3_y); + #endif + graph_add_graph_line(propmap->graph, l); + }else{ + free(l); + } +} + +static void link_materials(gpointer key, gpointer value, gpointer user_data) { + struct xy_properties *propmap = user_data; + struct matdb_material *mat = value; + if(!strcasecmp(mat->name->str, "vacuum")) return; + if(!strcasecmp(mat->name->str, "pvb")) return; + propmap->mat = mat; + g_hash_table_foreach(propmap->mdb->materials, &inner_link_materials, propmap); +} + +int main(int argc, char *argv[]) +{ + GtkWidget *window; + GtkWidget *graph; + GString *file = g_string_new("matdb.txt"); + int err=0; + struct matdb *mdb = read_matdb_dotcode(file, &err); + //fprintf(stderr, "read_matdb_dotcode(%s, %d)=%x", file->str, err, + //(int)mdb); + //fprintf(stderr, "err=%d\n", err); + //print_matdb(mdb); + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + graph = graph_widget_new(); + + struct xy_properties propmap; + propmap.xprop = g_string_new("a_lc"); + propmap.yprop = g_string_new("E_g_Gamma"); + propmap.graph = graph_widget_get_graph(GRAPH_WIDGET(graph)); + propmap.mdb = mdb; + g_hash_table_foreach(mdb->materials, &put_mat_in_graph, &propmap); + //graph_add_linear_connectors(propmap.graph); + g_hash_table_foreach(mdb->materials, &link_materials, &propmap); + graph_autoset_xaxis(propmap.graph, propmap.xprop); + graph_autoset_yaxis(propmap.graph, propmap.yprop); + + //Connect signals + g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); + + gtk_container_add(GTK_CONTAINER(window), graph); + /* + graph_add_point(graph_widget_get_graph(graph), 5, 3); + graph_add_point(graph_widget_get_graph(graph), 8, 12); + graph_add_point(graph_widget_get_graph(graph), 11, 48); + */ + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +}