mirror of
git://projects.qi-hardware.com/cae-tools.git
synced 2024-12-23 10:55:30 +02:00
130 lines
2.5 KiB
C
130 lines
2.5 KiB
C
/*
|
|
* extrude.c - 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.
|
|
*/
|
|
|
|
/*
|
|
* Known bugs:
|
|
*
|
|
* - negative x coordinates in shape produce overlapping faces
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
|
|
#include "ptrude.h"
|
|
#include "path.h"
|
|
#include "extrude.h"
|
|
|
|
|
|
static void cvt_3d(struct point *p, const struct vertex *v, double z)
|
|
{
|
|
p->x = v->x;
|
|
p->y = v->y;
|
|
p->z = z;
|
|
}
|
|
|
|
|
|
static void size(const struct path *p)
|
|
{
|
|
const struct vertex *v, *next;
|
|
double s = 0, sl = 0;
|
|
int n = 0;
|
|
|
|
if (!debug)
|
|
return;
|
|
for (v = p->vertices; v; v = next) {
|
|
next = v->next;
|
|
if (next)
|
|
s += hypot(v->x-next->x, v->y-next->y);
|
|
sl += v->len;
|
|
n++;
|
|
}
|
|
fprintf(stderr, "%d virt %g real %g\n", n, sl, s);
|
|
|
|
}
|
|
|
|
|
|
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 *data)
|
|
{
|
|
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;
|
|
|
|
cvt_3d(&a3, a, za);
|
|
cvt_3d(&b3, b, zb);
|
|
|
|
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,
|
|
double r, double d,
|
|
void (*face)(void *data, struct point a, struct point b, struct point c),
|
|
void *data)
|
|
{
|
|
const struct vertex *v, *next; /* current and next vertex */
|
|
struct path *prev, *curr; /* previous and current path */
|
|
struct path *tmp;
|
|
|
|
if (!path->vertices || !path->vertices->next)
|
|
return;
|
|
|
|
v = shape->vertices;
|
|
if (!v || !v->next)
|
|
return;
|
|
|
|
tmp = stretch_path(path, v->x, r);
|
|
size(tmp);
|
|
prev = round_path(tmp, r, d);
|
|
free_path(tmp);
|
|
size(prev);
|
|
|
|
while (v->next) {
|
|
next = v->next;
|
|
tmp = stretch_path(path, next->x, r);
|
|
size(tmp);
|
|
curr = round_path(tmp, r, d);
|
|
size(curr);
|
|
free_path(tmp);
|
|
|
|
mesh(prev, v->y, curr, next->y, face, data);
|
|
|
|
free_path(prev);
|
|
prev = curr;
|
|
v = next;
|
|
}
|
|
|
|
free_path(prev);
|
|
}
|