/*
 * ptrude.c - Extrusion of a 2D path along a perpendicular 2D path
 *
 * Written 2011 by Werner Almesberger
 * Copyright 2011 by 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 <unistd.h>
#include <string.h>
#include <math.h>

#include "path.h"
#include "extrude.h"
#include "ptrude.h"


int debug = 0;


static FILE *open_file(const char *name, const char *mode)
{
	FILE *file;

	if (!strcmp(name, "-"))
		return strcmp(mode, "r") ? stdout : stdin;

	file = fopen(name, mode);
	if (!file) {
		perror(name);
		exit(1);
	}
	return file;
}


static void close_file(FILE *file)
{
	if (file == stdin || file == stdout)
		return;
	if (fclose(file) == EOF) {
		perror("fclose");
		exit(1);
	}
}


static void do_face(void *data, struct point a, struct point b, struct point c)
{
	FILE *file = data;

	fprintf(file, "facet normal 0 0 0\n");
	fprintf(file, "  outer loop\n");
	fprintf(file, "  vertex %f %f %f\n", a.x, a.y, a.z);
	fprintf(file, "  vertex %f %f %f\n", b.x, b.y, b.z);
	fprintf(file, "  vertex %f %f %f\n", c.x, c.y, c.z);
	fprintf(file, "  endloop\nendfacet\n");
}


static void do_extrude(const struct path *path, const struct path *shape,
    double r, double d)
{
	FILE *file = stdout;

	fprintf(file, "solid ptrude\n");
	extrude(path, shape, r, d, do_face, file);
	fprintf(file, "endsolid ptrude\n");
}


static void usage(const char *name)
{
	fprintf(stderr,
"usage: %s shape radius tolerance\n"
"%6s %s path shape radius tolerance\n",
	    name, "", name);
	exit(1);
}


int main(int argc, char **argv)
{
	FILE *file;
	struct path *path = NULL;
	const struct path *shape;
	double r, d;
	char *end;
	int c;

	while ((c = getopt(argc, argv, "d")) != EOF)
		switch (c) {
		case 'd':
			debug = 1;
			break;
		default:
			usage(*argv);
		}

	switch (argc-optind) {
	case 3:
		break;
	case 4:
		file = open_file(argv[optind], "r");
		path = load_path(file);
		close_file(file);
		break;
	default:
		usage(*argv);
	}

	file = open_file(argv[argc-3], "r");
	shape = load_path(file);
	close_file(file);

	r = strtod(argv[argc-2], &end);
	if (*end || r <= 0)
		usage(*argv);
	d = strtod(argv[argc-1], &end);
	if (*end || d <= 0)
		usage (*argv);

	if (path) {
		/*
		 * We split the error budget evenly between path and shape.
		 */
		path_set_length(path);
		shape = round_path(shape, r, sqrt(d));
		do_extrude(path, shape, r, sqrt(d));
	} else {
		shape = round_path(shape, r, d);
		save_path(stdout, shape);
	}

	return 0;
}