[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: gEDA-user: Design changs required to mill PCBs?



> Do you still have the code? would you share? I have an old plotter and
> learned some HPGL years ago, even wrote some simple plotting tools. Now I
> would use HPGL as an example exporter with the scriptable PCB project.

I didn't see a response from Dave, but I've attached the code wrote to
work with my plotter last year.  It is able to convert a DXF file to
HPGL format.

Hope it helps.

Robert

/*
 * Copyright (C) 2005, 2006 Robert Fitzsimons
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 *
 * This is a basic program which can convert a CAD file in DXF format
 * to a HPGL file which can then be sent to a plotter.  Initially
 * developed for use with a HP 7475A plotter.
 *
 *
 * Email: robfitz at 273k dot net
 * Build: gcc -Wall -std=c99 -lm dxf2hpgl.c -o dxf2hpgl
 * Usage: dxf2hpgl <dxf filename> > output
 */

#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <math.h>

#define FLAG_TYPE_MASK     0xFF
#define FLAG_TYPE_POINT    0x01
#define FLAG_TYPE_LINE     0x02
#define FLAG_TYPE_CIRCLE   0x03
#define FLAG_USED        0x0100
#define FLAG_PRINTED     0x0200
#define FLAG_LINK        0x0400

struct point {
	double x;
	double y;
	double z;
};

struct line {
	struct point p1;
	struct point p2;
};

struct circle {
	struct point p;
	double radius;
};

struct object {
	struct object *next;
	int flags;
	char line_type[128];
	union {
		struct point point;
		struct line line;
		struct circle circle;
	} data;
};

struct object *object_list;

enum side {
	SIDE_X1Y1 = 1,
	SIDE_X2Y2 = 2
};

long int unit_convert(double unit) {
	return lround(unit * 1000.0);
}

enum side find_link_end(struct object *link_obj, enum side link_side, struct object **link_end) {
	struct object *obj;
	struct point *p;

	link_obj->flags |= (FLAG_LINK);
	p = (link_side == SIDE_X1Y1) ? (&link_obj->data.line.p1) : (&link_obj->data.line.p2);

	for (obj = object_list; obj != NULL; obj = obj->next) {
		if ((obj->flags & FLAG_LINK) || (obj->flags & FLAG_PRINTED) || (obj->flags & FLAG_USED) || ((obj->flags & FLAG_TYPE_MASK) != FLAG_TYPE_LINE)) {
			continue;
		}

		if ((p->x == obj->data.line.p1.x) && (p->y == obj->data.line.p1.y)) {
			return find_link_end(obj, SIDE_X2Y2, link_end);
		}
		if ((p->x == obj->data.line.p2.x) && (p->y == obj->data.line.p2.y)) {
			return find_link_end(obj, SIDE_X1Y1, link_end);
		}
	}

	if (*(link_end) == NULL) {
		*(link_end) = link_obj;
	}

	return link_side;
}

int print_link(struct object *link_obj, enum side link_side) {
	struct object *obj;
	struct point *p;

	link_obj->flags |= (FLAG_PRINTED | FLAG_USED);
	p = (link_side == SIDE_X1Y1) ? (&link_obj->data.line.p1) : (&link_obj->data.line.p2);

	for (obj = object_list; obj != NULL; obj = obj->next) {
		if ((obj->flags & FLAG_PRINTED) || (obj->flags & FLAG_USED) || ((obj->flags & FLAG_TYPE_MASK) != FLAG_TYPE_LINE)) {
			continue;
		}

		if ((p->x == obj->data.line.p1.x) && (p->y == obj->data.line.p1.y)) {
			fprintf(stdout, ",%ld,%ld", unit_convert(obj->data.line.p2.x), unit_convert(obj->data.line.p2.y));
			return print_link(obj, SIDE_X2Y2);
		}
		if ((p->x == obj->data.line.p2.x) && (p->y == obj->data.line.p2.y)) {
			fprintf(stdout, ",%ld,%ld", unit_convert(obj->data.line.p1.x), unit_convert(obj->data.line.p1.y));
			return print_link(obj, SIDE_X1Y1);
		}
	}

	return 0;
}

int print_line(struct object *object) {
	struct object *link_end = NULL;
	enum side link_side;

	link_side = find_link_end(object, SIDE_X1Y1, &link_end);

	if (link_side == SIDE_X1Y1) {
		fprintf(stdout, "PU%ld,%ld;PD%ld,%ld", unit_convert(link_end->data.line.p1.x), unit_convert(link_end->data.line.p1.y), unit_convert(link_end->data.line.p2.x), unit_convert(link_end->data.line.p2.y));
		print_link(link_end, SIDE_X2Y2);
	} else {
		fprintf(stdout, "PU%ld,%ld;PD%ld,%ld", unit_convert(link_end->data.line.p2.x), unit_convert(link_end->data.line.p2.y), unit_convert(link_end->data.line.p1.x), unit_convert(link_end->data.line.p1.y));
		print_link(link_end, SIDE_X1Y1);
	}

	fprintf(stdout, ";\n");

	return 0;
}

int print_circle(struct object *object) {
	fprintf(stdout, "PU%ld,%ld:CI%ld;\n", unit_convert(object->data.circle.p.x), unit_convert(object->data.circle.p.y), unit_convert(object->data.circle.radius));
	object->flags |= (FLAG_USED);

	return 0;
}


int io_buffer_size = 64;
char io_buffer[64 + 1];
char *io_buffer_start = io_buffer;
char *io_buffer_end = io_buffer;

int read_io_buffer(int fd) {
	int count = 0;
	ssize_t rc;

	while (count < io_buffer_size) {
		rc = read(fd, io_buffer, io_buffer_size);
		if (rc > 0) {
			count += rc;
		} else if (rc == 0) {
			break;
		} else {
			return -1;
		}
	}

	io_buffer_start = io_buffer;
	io_buffer_end = io_buffer_start + count;
	*(io_buffer_end) = '\0';

	return count;
}

int line_number;
size_t line_buffer_size;
char *line_buffer;
size_t line_buffer_length;

int read_line_buffer(int fd) {
	int rc;
	unsigned char c;

	line_buffer_length = 0;

	while (1) {
		if (!(io_buffer_start < io_buffer_end)) {
			rc = read_io_buffer(fd);
			if (rc <= 0) {
				return -1;
			}
		}

		c = *(io_buffer_start++);

		if (c == '\n') {
			break;
		}
		if (c == '\r') {
			c = *(io_buffer_start + 1);
			if (c == '\n') {
				io_buffer_start++;
			}
			break;
		}
		if (c == '\0') {
			break;
		}

		if (line_buffer_length >= line_buffer_size) {
			line_buffer_size += line_buffer_size + 32;
			line_buffer = realloc(line_buffer, line_buffer_size);
		}

		line_buffer[line_buffer_length++] = c;
	}

	line_buffer[line_buffer_length] = '\0';

	return line_buffer_length;
}

long int pushed_code;
char *pushed_value;

int get_code_value(int fd, long int *code, char **value) {
	int rc;

	if (pushed_value != NULL) {
		*(code) = pushed_code;
		*(value) = pushed_value;

		pushed_code = 0;
		pushed_value = NULL;
	} else {
		rc = read_line_buffer(fd);
		if (rc < 0) {
			return -1;
		}

		*(code) = strtol(line_buffer, NULL, 10);

		rc = read_line_buffer(fd);
		if (rc < 0) {
			return -1;
		}

		*(value) = line_buffer;

		line_number += 2;
	}

	// fprintf(stdout, "%d\t%ld\t%s\n", line_number, *(code), *(value));

	return 1;
}

int push_code_value(int fd, long int code, char *value) {
	pushed_code = code;
	pushed_value = value;

	return 1;
}

int main(int argc, char **argv) {
	int fd;
	int rc;
	long int code;
	char *value;
	int in_circle = 0;
	int in_line = 0;
	double x1;
	double y1;
	double x2;
	double y2;
	double rad;
	struct object *tmp;
	struct object *obj;
	char line_type[128];

	if (argc != 2) {
		fprintf(stderr, "Usage: dxf2hpgl <dxf filename> > output\n");
		return -1;
	}


	// Read line segments from dxf file

	fd = open(argv[1], O_RDONLY);
	if (fd != -1) {
		while (1) {
			rc = get_code_value(fd, &code, &value);
			if (rc < 0) {
				break;
			}

			if ((code == 0) && (strncasecmp(value, "SECTION", 7) == 0)) {
				rc = get_code_value(fd, &code, &value);
				if (rc < 0) {
					break;
				}

				if (code == 2) {
					if (strncasecmp(value, "ENTITIES", 8) == 0) {
						while (1) {
							rc = get_code_value(fd, &code, &value);
							if (rc < 0) {
								break;
							}

							if (code == 0) {
								if ((in_circle == 1) || (in_line == 1)) {
									obj = (struct object *)calloc(1, sizeof(struct object));

									strncpy(obj->line_type, line_type, sizeof(line_type));

									if (in_circle == 1) {
										obj->flags = FLAG_TYPE_CIRCLE;
										obj->data.circle.p.x = x1;
										obj->data.circle.p.y = y1;
										obj->data.circle.radius = rad;
									} else if (in_line == 1) {
										obj->flags = FLAG_TYPE_LINE;
										obj->data.line.p1.x = x1;
										obj->data.line.p1.y = y1;
										obj->data.line.p2.x = x2;
										obj->data.line.p2.y = y2;
									}

									obj->next = object_list;
									object_list = obj;
								}

								in_circle = in_line = 0;
								x1 = y1 = x2 = y2 = rad = 0.0;

								if (strncasecmp(value, "ENDSEC", 6) == 0) {
									break;
								} else if (strncasecmp(value, "CIRCLE", 6) == 0) {
									in_circle = 1;
								} else if (strncasecmp(value, "LINE", 4) == 0) {
									in_line = 1;
								}
							} else {
								switch (code) {
									case 8: strncpy(line_type, value, sizeof(line_type)); break;
									case 10: x1 = strtod(value, NULL); break;
									case 11: x2 = strtod(value, NULL); break;
									case 20: y1 = strtod(value, NULL); break;
									case 21: y2 = strtod(value, NULL); break;
									case 40: rad = strtod(value, NULL); break;
								}
							}
						}
					} else {
						while (1) {
							rc = get_code_value(fd, &code, &value);
							if (rc < 0) {
								break;
							}

							if ((code == 0) && (strncasecmp(value, "ENDSEC", 6) == 0)) {
								break;
							}
						}
					}
				}
			}
		}

		if (close(fd) == -1) {
			fprintf(stderr, "Error closing file\n");
			return -1;
		}
	} else {
		fprintf(stderr, "Error opening file\n");
		return -1;
	}


	// Write out line segments

	fprintf(stdout, "\x1b.(;\n\x1b.I81;;17:\n\x1b.N;19:\nIN;\nSC;\nPU;\nSP1;\nLT;\nVS1;\n\n");

	for (obj = object_list; obj != NULL; obj = obj->next) {
		if (obj->flags & FLAG_USED) {
			continue;
		}

		switch ((obj->flags & FLAG_TYPE_MASK)) {
			case FLAG_TYPE_CIRCLE:
				print_circle(obj);
				break;
			case FLAG_TYPE_LINE:
				print_line(obj);
				break;
		}
	}

	fprintf(stdout, "\nPU;\nSP;\nIN;\n\n");


	// Free allocated memory

	obj = object_list;
	while (obj != NULL) {
		tmp = obj;
		obj = obj->next;
		free(tmp);
	}

	free(line_buffer);


	return 0;
}


_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user