mirror of
git://projects.qi-hardware.com/cae-tools.git
synced 2024-12-22 23:16:27 +02:00
ptrude/: changed extrusion from xy path to xz path; variable number of faces
This commit is contained in:
parent
7ef626988c
commit
ee634458dc
119
ptrude/extrude.c
119
ptrude/extrude.c
@ -20,104 +20,85 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "extrude.h"
|
#include "extrude.h"
|
||||||
|
|
||||||
|
|
||||||
#define alloc_tn(t, n) ((t *) malloc(sizeof(t)*(n)))
|
static void cvt_3d(struct point *p, const struct vertex *v, double z)
|
||||||
|
|
||||||
|
|
||||||
static void slice(double x, double y, double nx, double ny,
|
|
||||||
const struct path *shape, struct point *p)
|
|
||||||
{
|
{
|
||||||
const struct vertex *v;
|
p->x = v->x;
|
||||||
|
p->y = v->y;
|
||||||
for (v = shape->vertices; v; v = v->next) {
|
p->z = z;
|
||||||
p->x = x+nx*v->x;
|
|
||||||
p->y = y+ny*v->x;
|
|
||||||
p->z = v->y;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void mesh(const struct point *a, const struct point *b, int n,
|
static void mesh(const struct path *pa, double za,
|
||||||
|
const struct path *pb, double zb,
|
||||||
void (*face)(void *data, struct point a, struct point b, struct point c),
|
void (*face)(void *data, struct point a, struct point b, struct point c),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
int i;
|
const struct vertex *a = pa->vertices;
|
||||||
|
const struct vertex *b = pb->vertices;
|
||||||
|
double sa = 0, sb = 0; /* total distance traveled on path */
|
||||||
|
double da, db;
|
||||||
|
struct point a3, b3, n;
|
||||||
|
|
||||||
for (i = 0; i != n-1; i++) {
|
cvt_3d(&a3, a, za);
|
||||||
face(data, a[i], b[i], a[i+1]);
|
cvt_3d(&b3, b, zb);
|
||||||
face(data, a[i+1], b[i], b[i+1]);
|
while (a->next || b->next) {
|
||||||
|
da = fabs(sa+a->len-sb);
|
||||||
|
db = fabs(sb+b->len-sa);
|
||||||
|
if ((a->next && da < db) || !b->next) {
|
||||||
|
cvt_3d(&n, a->next, za);
|
||||||
|
face(data, a3, n, b3);
|
||||||
|
a3 = n;
|
||||||
|
sa += a->len;
|
||||||
|
a = a->next;
|
||||||
|
} else {
|
||||||
|
cvt_3d(&n, b->next, zb);
|
||||||
|
face(data, b3, a3, n);
|
||||||
|
b3 = n;
|
||||||
|
sb += b->len;
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void extrude(const struct path *path, const struct path *shape,
|
void extrude(const struct path *path, const struct path *shape,
|
||||||
|
double r, double d,
|
||||||
void (*face)(void *data, struct point a, struct point b, struct point c),
|
void (*face)(void *data, struct point a, struct point b, struct point c),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
const struct vertex *v; /* current vertex (for iteration) */
|
const struct vertex *v, *next; /* current and next vertex */
|
||||||
const struct vertex *a, *b, *c; /* previous, current, next vertex */
|
struct path *prev, *curr; /* previous and current path */
|
||||||
struct point *prev, *this; /* previous and current slice */
|
struct path *tmp;
|
||||||
double nx, ny; /* 2D normals */
|
|
||||||
double f; /* factor for normalization */
|
|
||||||
double tx, ty; /* temporary 2D normals */
|
|
||||||
int n = 0; /* number of vertices in shape */
|
|
||||||
|
|
||||||
if (!path->vertices || !path->vertices->next || !shape->vertices)
|
if (!path->vertices || !path->vertices->next)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (v = shape->vertices; v; v = v->next)
|
v = shape->vertices;
|
||||||
n++;
|
if (!v || !v->next)
|
||||||
|
return;
|
||||||
|
|
||||||
prev = alloc_tn(struct point, n);
|
tmp = stretch_path(path, v->x);
|
||||||
this = alloc_tn(struct point, n);
|
prev = round_path(tmp, r, d);
|
||||||
|
free_path(tmp);
|
||||||
|
|
||||||
a = path->vertices;
|
while (v->next) {
|
||||||
b = a->next;
|
next = v->next;
|
||||||
nx = b->y-a->y;
|
tmp = stretch_path(path, next->x);
|
||||||
ny = a->x-b->x;
|
curr = round_path(tmp, r, d);
|
||||||
f = hypot(nx, ny);
|
free_path(tmp);
|
||||||
slice(a->x, a->y, nx/f, ny/f, shape, prev);
|
|
||||||
|
|
||||||
for (v = path->vertices->next; v->next; v = v->next) {
|
mesh(prev, v->y, curr, next->y, face, data);
|
||||||
b = v;
|
|
||||||
c = v->next;
|
|
||||||
|
|
||||||
tx = b->y-a->y;
|
free_path(prev);
|
||||||
ty = a->x-b->x;
|
prev = curr;
|
||||||
f = hypot(tx, ty);
|
v = next;
|
||||||
nx = tx/f;
|
|
||||||
ny = ty/f;
|
|
||||||
|
|
||||||
tx = c->y-b->y;
|
|
||||||
ty = b->x-c->x;
|
|
||||||
f = hypot(tx, ty);
|
|
||||||
nx += tx/f;
|
|
||||||
ny += ty/f;
|
|
||||||
|
|
||||||
slice(b->x, b->y, nx/2, ny/2, shape, this);
|
|
||||||
mesh(prev, this, n, face, data);
|
|
||||||
|
|
||||||
memcpy(prev, this, sizeof(*prev)*n);
|
|
||||||
|
|
||||||
a = v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nx = v->y-a->y;
|
free_path(prev);
|
||||||
ny = a->x-v->x;
|
|
||||||
f = hypot(nx, ny);
|
|
||||||
|
|
||||||
slice(v->x, v->y, nx/f, ny/f, shape, this);
|
|
||||||
mesh(prev, this, n, face, data);
|
|
||||||
|
|
||||||
/* @@@ To do: close shape and close top and bottom */
|
|
||||||
|
|
||||||
free(prev);
|
|
||||||
free(this);
|
|
||||||
}
|
}
|
||||||
|
26
ptrude/extrude.h
Normal file
26
ptrude/extrude.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* extrude.h - Perform the extrusion
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXTRUDE_H
|
||||||
|
#define EXTRUDE_H
|
||||||
|
|
||||||
|
struct point {
|
||||||
|
double x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void extrude(const struct path *path, const struct path *shape,
|
||||||
|
double r, double d,
|
||||||
|
void (*face)(void *data, struct point a, struct point b, struct point c),
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
#endif /* !EXTRUDE_H */
|
@ -64,12 +64,13 @@ static void do_face(void *data, struct point a, struct point b, struct point c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void do_extrude(const struct path *path, const struct path *shape)
|
static void do_extrude(const struct path *path, const struct path *shape,
|
||||||
|
double r, double d)
|
||||||
{
|
{
|
||||||
FILE *file = stdout;
|
FILE *file = stdout;
|
||||||
|
|
||||||
fprintf(file, "solid ptrude\n");
|
fprintf(file, "solid ptrude\n");
|
||||||
extrude(path, shape, do_face, file);
|
extrude(path, shape, r, d, do_face, file);
|
||||||
fprintf(file, "endsolid ptrude\n");
|
fprintf(file, "endsolid ptrude\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +88,8 @@ static void usage(const char *name)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
const struct path *path = NULL, *shape;
|
struct path *path = NULL;
|
||||||
|
const struct path *shape;
|
||||||
double r, d;
|
double r, d;
|
||||||
char *end;
|
char *end;
|
||||||
int c;
|
int c;
|
||||||
@ -128,9 +130,9 @@ int main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* We split the error budget evenly between path and shape.
|
* We split the error budget evenly between path and shape.
|
||||||
*/
|
*/
|
||||||
path = round_path(path, r, sqrt(d));
|
path_set_length(path);
|
||||||
shape = round_path(shape, r, sqrt(d));
|
shape = round_path(shape, r, sqrt(d));
|
||||||
do_extrude(path, shape);
|
do_extrude(path, shape, r, sqrt(d));
|
||||||
} else {
|
} else {
|
||||||
shape = round_path(shape, r, d);
|
shape = round_path(shape, r, d);
|
||||||
save_path(stdout, shape);
|
save_path(stdout, shape);
|
||||||
|
Loading…
Reference in New Issue
Block a user