[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