/*
 * p2d_gnuplot.c - File I/O in gnuplot format
 *
 * Written 2012 by Werner Almesberger
 * Copyright 2012 Werner Almesberger
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */


#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <errno.h>

#include "poly2d.h"


#define	EPSILON	1e-6


static void check_closed(struct p2d *p)
{
	if (!p)
		return;
	if (hypot(p->v->x-p->last->x, p->v->y-p->last->y) > EPSILON)
		return;
	free(p->last);
	p->last = p->v;
}


struct p2d *p2d_read_gnuplot(FILE *file)
{
	struct p2d *res = NULL, **last = &res, *p = NULL;
	char buf[1024];
	double x, y;
	int n;

	while (fgets(buf, sizeof(buf), file)) {
		if (*buf == '#')
			continue;
		n = sscanf(buf, "%lf %lf\n", &x, &y);
		switch (n) {
		case -1:
			check_closed(p);
			p = NULL;
			break;
		case 2:
			break;
		default:
			errno = EINVAL;
			return NULL;
		}
		if (!p) {
			p = p2d_new();
			*last = p;
			last = &p->next;
		}
		p2d_append(p, v2d_new(x, y));
	}
	check_closed(p);
	return res;
}


int p2d_write_gnuplot(FILE *file, const struct p2d *p)
{
	const struct v2d *v;

	v = p->v; 
	while (v) {
		if (fprintf(file, "%g %g\n", v->x, v->y) < 0)
			return 0;
		v = v->next;
		if (v == p->v) {
			if (fprintf(file, "%g %g\n", v->x, v->y) < 0)
				return 0;
			break;
		}
	}
	return fprintf(file, "\n") >= 0;
}


int p2d_write_gnuplot_all(FILE *file, const struct p2d *p)
{
	while (p) {
		if (!p2d_write_gnuplot(file, p))
			return 0;
		p = p->next;
	}
	return 1;
}