From ca8d26a012451771595cf54194888b1984c5dd17 Mon Sep 17 00:00:00 2001 From: "trelane@digitasaru.net" Date: Mon, 12 Oct 2009 07:26:14 -0500 Subject: [PATCH] Moving files around, starting libtoolization. --- Makefile | 68 ---------- Makefile.am | 38 ++++++ configure.ac | 128 +++++++++++++++++++ graph.c | 242 ----------------------------------- graph.h | 107 ---------------- graphwidget.c | 252 ------------------------------------- graphwidget.h | 55 -------- matdb-dotcode.c | 346 --------------------------------------------------- matdb-dotcode.h | 30 ----- matdb.c | 73 ----------- matdb.h | 50 -------- scdataviz.c | 183 --------------------------- src/graph.c | 242 +++++++++++++++++++++++++++++++++++ src/graph.h | 107 ++++++++++++++++ src/graphwidget.c | 252 +++++++++++++++++++++++++++++++++++++ src/graphwidget.h | 55 ++++++++ src/matdb-dotcode.c | 346 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/matdb-dotcode.h | 30 +++++ src/matdb.c | 73 +++++++++++ src/matdb.h | 50 ++++++++ src/scdataviz.c | 183 +++++++++++++++++++++++++++ 21 files changed, 1504 insertions(+), 1406 deletions(-) delete mode 100644 Makefile create mode 100644 Makefile.am create mode 100644 configure.ac delete mode 100644 graph.c delete mode 100644 graph.h delete mode 100644 graphwidget.c delete mode 100644 graphwidget.h delete mode 100644 matdb-dotcode.c delete mode 100644 matdb-dotcode.h delete mode 100644 matdb.c delete mode 100644 matdb.h delete mode 120000 matdb.txt delete mode 100644 scdataviz.c create mode 100644 src/graph.c create mode 100644 src/graph.h create mode 100644 src/graphwidget.c create mode 100644 src/graphwidget.h create mode 100644 src/matdb-dotcode.c create mode 100644 src/matdb-dotcode.h create mode 100644 src/matdb.c create mode 100644 src/matdb.h create mode 100644 src/scdataviz.c 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; +} -- 1.7.9.5